LCOV - code coverage report
Current view: top level - drivers/net/intel/common - tx.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 84 0.0 %
Date: 2026-10-01 18:19:24 Functions: 0 2 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 202 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                 :            : #include <rte_io.h>
      13                 :            : #include <rte_byteorder.h>
      14                 :            : 
      15                 :            : #define CI_VPMD_TX_BURST            32
      16                 :            : #define CI_VPMD_TX_MAX_FREE_BUF     64
      17                 :            : 
      18                 :            : /* basic vector path */
      19                 :            : #define CI_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
      20                 :            : /* offload vector path */
      21                 :            : #define CI_TX_VEC_OFFLOAD_PATH_OFFLOADS (       \
      22                 :            :                 CI_TX_VECTOR_OFFLOADS |         \
      23                 :            :                 RTE_ETH_TX_OFFLOAD_VLAN_INSERT |        \
      24                 :            :                 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |         \
      25                 :            :                 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |         \
      26                 :            :                 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |          \
      27                 :            :                 RTE_ETH_TX_OFFLOAD_TCP_CKSUM)
      28                 :            : /* offload vector path with context descriptor */
      29                 :            : #define CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS (   \
      30                 :            :                 CI_TX_VECTOR_OFFLOADS |         \
      31                 :            :                 CI_TX_VEC_OFFLOAD_PATH_OFFLOADS |       \
      32                 :            :                 RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |   \
      33                 :            :                 RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |    \
      34                 :            :                 RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
      35                 :            : 
      36                 :            : /* Common TX Descriptor QW1 Field Definitions */
      37                 :            : #define CI_TXD_QW1_DTYPE_S      0
      38                 :            : #define CI_TXD_QW1_DTYPE_M      (0xFUL << CI_TXD_QW1_DTYPE_S)
      39                 :            : #define CI_TXD_QW1_CMD_S        4
      40                 :            : #define CI_TXD_QW1_CMD_M        (0xFFFUL << CI_TXD_QW1_CMD_S)
      41                 :            : #define CI_TXD_QW1_OFFSET_S     16
      42                 :            : #define CI_TXD_QW1_OFFSET_M     (0x3FFFFULL << CI_TXD_QW1_OFFSET_S)
      43                 :            : #define CI_TXD_QW1_TX_BUF_SZ_S  34
      44                 :            : #define CI_TXD_QW1_TX_BUF_SZ_M  (0x3FFFULL << CI_TXD_QW1_TX_BUF_SZ_S)
      45                 :            : #define CI_TXD_QW1_L2TAG1_S     48
      46                 :            : #define CI_TXD_QW1_L2TAG1_M     (0xFFFFULL << CI_TXD_QW1_L2TAG1_S)
      47                 :            : 
      48                 :            : /* Common Descriptor Types */
      49                 :            : #define CI_TX_DESC_DTYPE_DATA           0x0
      50                 :            : #define CI_TX_DESC_DTYPE_CTX            0x1
      51                 :            : #define CI_TX_DESC_DTYPE_DESC_DONE      0xF
      52                 :            : 
      53                 :            : /* Common TX Descriptor Command Flags */
      54                 :            : #define CI_TX_DESC_CMD_EOP              0x0001
      55                 :            : #define CI_TX_DESC_CMD_RS               0x0002
      56                 :            : #define CI_TX_DESC_CMD_ICRC             0x0004
      57                 :            : #define CI_TX_DESC_CMD_IL2TAG1          0x0008
      58                 :            : #define CI_TX_DESC_CMD_DUMMY            0x0010
      59                 :            : #define CI_TX_DESC_CMD_IIPT_IPV6        0x0020
      60                 :            : #define CI_TX_DESC_CMD_IIPT_IPV4        0x0040
      61                 :            : #define CI_TX_DESC_CMD_IIPT_IPV4_CSUM   0x0060
      62                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_TCP     0x0100
      63                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_SCTP    0x0200
      64                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_UDP     0x0300
      65                 :            : 
      66                 :            : /* Common TX Context Descriptor Commands */
      67                 :            : #define CI_TX_CTX_DESC_TSO              0x01
      68                 :            : #define CI_TX_CTX_DESC_TSYN             0x02
      69                 :            : #define CI_TX_CTX_DESC_IL2TAG2          0x04
      70                 :            : 
      71                 :            : /* Common TX Context Descriptor QW0 Field Shifts */
      72                 :            : #define CI_TXD_CTX_QW0_L2TAG2_S         32
      73                 :            : #define CI_TXD_CTX_QW0_EIPT_S           0  /* 2 BITS - external IP type */
      74                 :            : #define CI_TXD_CTX_QW0_EIPLEN_S         2  /* 7 BITS - external IP header length */
      75                 :            : #define CI_TXD_CTX_QW0_NATT_S           9  /* 2 BITS - L4 tunnel type */
      76                 :            : #define CI_TXD_CTX_QW0_EIP_NOINC_S      11 /* 1 BIT  - external IP ID not incremented */
      77                 :            : #define CI_TXD_CTX_QW0_NATLEN_S         12 /* 7 BITS - L4 tunnel header length */
      78                 :            : #define CI_TXD_CTX_QW0_L4T_CS_S         23 /* 1 BIT  - tunnel UDP checksum enable */
      79                 :            : 
      80                 :            : /**
      81                 :            :  * Enum for the external (outer) IP type field of a Tx context descriptor's
      82                 :            :  * tunnel parameters (QW0 bits 0-1).
      83                 :            :  */
      84                 :            : enum ci_tx_ctx_eipt {
      85                 :            :         CI_TX_CTX_EIPT_NONE,
      86                 :            :         CI_TX_CTX_EIPT_IPV6,
      87                 :            :         CI_TX_CTX_EIPT_IPV4_NO_CSUM,
      88                 :            :         CI_TX_CTX_EIPT_IPV4,
      89                 :            : };
      90                 :            : 
      91                 :            : #define CI_TXD_CTX_UDP_TUNNELING        (0x1ULL << CI_TXD_CTX_QW0_NATT_S)
      92                 :            : #define CI_TXD_CTX_GRE_TUNNELING        (0x2ULL << CI_TXD_CTX_QW0_NATT_S)
      93                 :            : #define CI_TXD_CTX_QW0_L4T_CS_M         (0x1ULL << CI_TXD_CTX_QW0_L4T_CS_S)
      94                 :            : 
      95                 :            : /**
      96                 :            :  * Enum to specify where a VLAN tag is to be placed for packet Tx.
      97                 :            :  */
      98                 :            : enum ci_l2tag_pos {
      99                 :            :         /** Insert via the data descriptor's L2Tag1 field. */
     100                 :            :         CI_TAG_IN_DATA_DESC,
     101                 :            : 
     102                 :            :         /** Insert via the context descriptor's L2Tag2 field.
     103                 :            :          * NOTE: When set, drivers must set the VLAN tag in the context
     104                 :            :          * descriptor callback function, rather than relying on the
     105                 :            :          * common Tx code to insert it.
     106                 :            :          */
     107                 :            :         CI_TAG_IN_CTX_DESC,
     108                 :            : };
     109                 :            : 
     110                 :            : /* Common TX Descriptor Length Field Shifts */
     111                 :            : #define CI_TX_DESC_LEN_MACLEN_S         0  /* 7 BITS */
     112                 :            : #define CI_TX_DESC_LEN_IPLEN_S          7  /* 7 BITS */
     113                 :            : #define CI_TX_DESC_LEN_L4_LEN_S         14 /* 4 BITS */
     114                 :            : 
     115                 :            : /* Common maximum data per TX descriptor */
     116                 :            : #define CI_MAX_DATA_PER_TXD     (CI_TXD_QW1_TX_BUF_SZ_M >> CI_TXD_QW1_TX_BUF_SZ_S)
     117                 :            : 
     118                 :            : /* Common TX maximum burst size for chunked transmission in simple paths */
     119                 :            : #define CI_TX_MAX_BURST 32
     120                 :            : 
     121                 :            : /* Common TX maximum free buffer size for batched bulk freeing */
     122                 :            : #define CI_TX_MAX_FREE_BUF_SZ 64
     123                 :            : 
     124                 :            : /* Common TX descriptor command flags for simple transmit */
     125                 :            : #define CI_TX_DESC_CMD_DEFAULT (CI_TX_DESC_CMD_ICRC | CI_TX_DESC_CMD_EOP)
     126                 :            : 
     127                 :            : /* Checksum offload mask to identify packets requesting offload */
     128                 :            : #define CI_TX_CKSUM_OFFLOAD_MASK (RTE_MBUF_F_TX_IP_CKSUM |               \
     129                 :            :                                    RTE_MBUF_F_TX_L4_MASK |               \
     130                 :            :                                    RTE_MBUF_F_TX_TCP_SEG |               \
     131                 :            :                                    RTE_MBUF_F_TX_UDP_SEG |               \
     132                 :            :                                    RTE_MBUF_F_TX_OUTER_IP_CKSUM |        \
     133                 :            :                                    RTE_MBUF_F_TX_OUTER_UDP_CKSUM)
     134                 :            : 
     135                 :            : /**
     136                 :            :  * Common TX offload union for Intel drivers.
     137                 :            :  * Supports both basic offloads (l2_len, l3_len, l4_len, tso_segsz) and
     138                 :            :  * extended offloads (outer_l2_len, outer_l3_len) for tunneling support.
     139                 :            :  */
     140                 :            : union ci_tx_offload {
     141                 :            :         uint64_t data;
     142                 :            :         struct {
     143                 :            :                 uint64_t l2_len:7;        /**< L2 (MAC) Header Length. */
     144                 :            :                 uint64_t l3_len:9;        /**< L3 (IP) Header Length. */
     145                 :            :                 uint64_t l4_len:8;        /**< L4 Header Length. */
     146                 :            :                 uint64_t tso_segsz:16;    /**< TCP TSO segment size */
     147                 :            :                 uint64_t outer_l2_len:8;  /**< outer L2 Header Length */
     148                 :            :                 uint64_t outer_l3_len:16; /**< outer L3 Header Length */
     149                 :            :         };
     150                 :            : };
     151                 :            : 
     152                 :            : /*
     153                 :            :  * Structure of a 16-byte Tx descriptor common across i40e, ice, iavf and idpf drivers
     154                 :            :  */
     155                 :            : struct ci_tx_desc {
     156                 :            :         uint64_t buffer_addr; /* Address of descriptor's data buf */
     157                 :            :         uint64_t cmd_type_offset_bsz;
     158                 :            : };
     159                 :            : 
     160                 :            : /* forward declaration of the common intel (ci) queue structure */
     161                 :            : struct ci_tx_queue;
     162                 :            : 
     163                 :            : /**
     164                 :            :  * Structure associated with each descriptor of the TX ring of a TX queue.
     165                 :            :  */
     166                 :            : struct ci_tx_entry {
     167                 :            :         struct rte_mbuf *mbuf; /* mbuf associated with TX desc, if any. */
     168                 :            :         uint16_t next_id; /* Index of next descriptor in ring. */
     169                 :            :         uint16_t first_id; /* Split-queue: first sw_id of packet at EOP entry. */
     170                 :            : };
     171                 :            : 
     172                 :            : /**
     173                 :            :  * Structure associated with each descriptor of the TX ring of a TX queue in vector Tx.
     174                 :            :  */
     175                 :            : struct ci_tx_entry_vec {
     176                 :            :         struct rte_mbuf *mbuf; /* mbuf associated with TX desc, if any. */
     177                 :            : };
     178                 :            : 
     179                 :            : typedef void (*ice_tx_release_mbufs_t)(struct ci_tx_queue *txq);
     180                 :            : 
     181                 :            : struct ci_tx_queue {
     182                 :            :         union { /* TX ring virtual address */
     183                 :            :                 volatile struct ci_tx_desc *ci_tx_ring;
     184                 :            :                 volatile union ixgbe_adv_tx_desc *ixgbe_tx_ring;
     185                 :            :         };
     186                 :            :         volatile uint8_t *qtx_tail;               /* register address of tail */
     187                 :            :         union {
     188                 :            :                 struct ci_tx_entry *sw_ring; /* virtual address of SW ring */
     189                 :            :                 struct ci_tx_entry_vec *sw_ring_vec;
     190                 :            :         };
     191                 :            :         /* Scalar TX path: Array tracking last_id at each RS threshold boundary */
     192                 :            :         uint16_t *rs_last_id;
     193                 :            :         uint16_t nb_tx_desc;           /* number of TX descriptors */
     194                 :            :         uint16_t tx_tail; /* current value of tail register */
     195                 :            :         /* index to last TX descriptor to have been cleaned */
     196                 :            :         uint16_t last_desc_cleaned;
     197                 :            :         /* Total number of TX descriptors ready to be allocated. */
     198                 :            :         uint16_t nb_tx_free;
     199                 :            :         /* Start freeing TX buffers if there are less free descriptors than
     200                 :            :          * this value.
     201                 :            :          */
     202                 :            :         uint16_t tx_free_thresh;
     203                 :            :         /* Number of TX descriptors to use before RS bit is set. */
     204                 :            :         uint16_t tx_rs_thresh;
     205                 :            :         /* Scalar TX path: log2 of tx_rs_thresh for efficient bit operations */
     206                 :            :         uint8_t log2_rs_thresh;
     207                 :            :         uint16_t port_id;  /* Device port identifier. */
     208                 :            :         uint16_t queue_id; /* TX queue index. */
     209                 :            :         uint16_t reg_idx;
     210                 :            :         uint16_t tx_next_dd;
     211                 :            :         uint16_t tx_next_rs;
     212                 :            :         /* Mempool pointer for fast release of mbufs.
     213                 :            :          * NULL if disabled, UINTPTR_MAX if enabled and not yet known.
     214                 :            :          * Set at first use (if enabled and not yet known).
     215                 :            :          */
     216                 :            :         struct rte_mempool *fast_free_mp;
     217                 :            :         uint64_t offloads;
     218                 :            :         uint64_t mbuf_errors;
     219                 :            :         rte_iova_t tx_ring_dma;        /* TX ring DMA address */
     220                 :            :         bool tx_deferred_start; /* don't start this queue in dev start */
     221                 :            :         bool q_set;             /* indicate if tx queue has been configured */
     222                 :            :         bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple paths) */
     223                 :            :         bool use_ctx;           /* with ctx info, each pkt needs two desc in vec paths */
     224                 :            :         union {                  /* the VSI this queue belongs to */
     225                 :            :                 struct i40e_vsi *i40e_vsi;
     226                 :            :                 struct iavf_vsi *iavf_vsi;
     227                 :            :                 struct ice_vsi *ice_vsi;
     228                 :            :         };
     229                 :            :         const struct rte_memzone *mz;
     230                 :            : 
     231                 :            :         union {
     232                 :            :                 struct { /* ICE driver specific values */
     233                 :            :                         struct ice_txtime *tsq; /* Tx Time based queue */
     234                 :            :                         uint32_t q_teid; /* TX schedule node id. */
     235                 :            :                 };
     236                 :            :                 struct { /* I40E driver specific values */
     237                 :            :                         uint8_t dcb_tc;
     238                 :            :                 };
     239                 :            :                 struct { /* iavf driver specific values */
     240                 :            :                         uint16_t ipsec_crypto_pkt_md_offset;
     241                 :            : #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1 BIT(0)
     242                 :            : #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
     243                 :            :                         uint8_t vlan_flag;
     244                 :            :                         uint8_t tc;
     245                 :            :                         bool lldp_enabled;
     246                 :            :                 };
     247                 :            :                 struct { /* ixgbe specific values */
     248                 :            :                         const struct ixgbe_txq_ops *ops;
     249                 :            :                         struct ixgbe_advctx_info *ctx_cache;
     250                 :            :                         uint8_t ctx_curr;
     251                 :            :                         uint8_t pthresh;   /**< Prefetch threshold register. */
     252                 :            :                         uint8_t hthresh;   /**< Host threshold register. */
     253                 :            :                         uint8_t wthresh;   /**< Write-back threshold reg. */
     254                 :            :                         uint8_t using_ipsec;  /**< indicates that IPsec TX feature is in use */
     255                 :            :                         uint8_t is_vf;   /**< indicates that this is a VF queue */
     256                 :            :                         uint8_t vf_ctx_initialized; /**< VF context descriptors initialized */
     257                 :            :                 };
     258                 :            :                 struct { /* idpf specific values */
     259                 :            :                                 struct idpf_flex_tx_sched_desc *desc_ring;
     260                 :            :                                 struct idpf_complq *complq;
     261                 :            :                                 uint32_t latch_idx; /* Tx timestamp latch index */
     262                 :            :                                 uint16_t sw_nb_desc;
     263                 :            :                                 uint16_t sw_tail;
     264                 :            :                                 uint16_t rs_compl_count;
     265                 :            :                 };
     266                 :            :         };
     267                 :            : };
     268                 :            : 
     269                 :            : struct ci_tx_path_features {
     270                 :            :         uint32_t tx_offloads;
     271                 :            :         enum rte_vect_max_simd simd_width;
     272                 :            :         bool simple_tx;
     273                 :            :         bool disabled;
     274                 :            :         bool single_queue;
     275                 :            : };
     276                 :            : 
     277                 :            : struct ci_tx_path_info {
     278                 :            :         eth_tx_burst_t pkt_burst;
     279                 :            :         const char *info;
     280                 :            :         struct ci_tx_path_features features;
     281                 :            :         eth_tx_prep_t pkt_prep;
     282                 :            :         bool supports_ctx;
     283                 :            : };
     284                 :            : 
     285                 :            : /* basic check for a vector-driver capable Tx queue.
     286                 :            :  * Individual drivers may have other further tests beyond this.
     287                 :            :  */
     288                 :            : static inline bool
     289                 :            : ci_txq_vec_capable(uint16_t rs_thresh)
     290                 :            : {
     291         [ #  # ]:          0 :         return rs_thresh >= CI_VPMD_TX_BURST && rs_thresh <= CI_VPMD_TX_MAX_FREE_BUF;
     292                 :            : }
     293                 :            : 
     294                 :            : static __rte_always_inline void
     295                 :            : ci_tx_backlog_entry(struct ci_tx_entry *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     296                 :            : {
     297                 :            :         for (uint16_t i = 0; i < (int)nb_pkts; ++i)
     298                 :            :                 txep[i].mbuf = tx_pkts[i];
     299                 :            : }
     300                 :            : 
     301                 :            : static __rte_always_inline void
     302                 :            : ci_tx_backlog_entry_vec(struct ci_tx_entry_vec *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     303                 :            : {
     304   [ #  #  #  #  :          0 :         for (uint16_t i = 0; i < nb_pkts; ++i)
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     305                 :          0 :                 txep[i].mbuf = tx_pkts[i];
     306                 :            : }
     307                 :            : 
     308                 :            : 
     309                 :            : /* Write the Tx tail register, byte-swapped for hardware regardless of host endianness. */
     310                 :            : static __rte_always_inline void
     311                 :            : ci_tx_qtx_tail_write(struct ci_tx_queue *txq, uint16_t tx_id)
     312                 :            : {
     313                 :          0 :         rte_write32_wc(rte_cpu_to_le_32((uint32_t)tx_id), txq->qtx_tail);
     314                 :            : }
     315                 :            : 
     316                 :            : #define IETH_VPMD_TX_MAX_FREE_BUF 64
     317                 :            : 
     318                 :            : typedef int (*ci_desc_done_fn)(struct ci_tx_queue *txq, uint16_t idx);
     319                 :            : 
     320                 :            : static __rte_always_inline int
     321                 :            : ci_tx_free_bufs_vec(struct ci_tx_queue *txq, ci_desc_done_fn desc_done, bool ctx_descs)
     322                 :            : {
     323                 :            :         int nb_free = 0;
     324                 :            :         struct rte_mbuf *free[IETH_VPMD_TX_MAX_FREE_BUF];
     325                 :            :         struct rte_mbuf *m;
     326                 :            : 
     327                 :            :         /* check DD bits on threshold descriptor */
     328   [ #  #  #  #  :          0 :         if (!desc_done(txq, txq->tx_next_dd))
             #  #  #  # ]
     329                 :            :                 return 0;
     330                 :            : 
     331                 :          0 :         const uint32_t n = txq->tx_rs_thresh >> ctx_descs;
     332                 :            : 
     333                 :            :         /* first buffer to free from S/W ring is at index
     334                 :            :          * tx_next_dd - (tx_rs_thresh - 1)
     335                 :            :          */
     336                 :          0 :         struct ci_tx_entry_vec *txep = txq->sw_ring_vec;
     337                 :          0 :         txep += (txq->tx_next_dd >> ctx_descs) - (n - 1);
     338                 :            : 
     339                 :            :         /* is fast-free enabled? */
     340                 :            :         struct rte_mempool *mp =
     341                 :          0 :                         likely(txq->fast_free_mp != (void *)UINTPTR_MAX) ?
     342   [ #  #  #  #  :          0 :                         txq->fast_free_mp :
             #  #  #  # ]
     343                 :          0 :                         (txq->fast_free_mp = txep[0].mbuf->pool);
     344                 :            : 
     345   [ #  #  #  #  :          0 :         if (mp != NULL && (n & 31) == 0) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     346                 :            :                 static_assert(sizeof(*txep) == sizeof(struct rte_mbuf *),
     347                 :            :                                 "txep array is not similar to an array of rte_mbuf pointers");
     348                 :            :                 rte_mbuf_raw_free_bulk(mp, (void *)txep, n);
     349                 :          0 :                 goto done;
     350                 :            :         }
     351                 :            : 
     352   [ #  #  #  #  :          0 :         m = rte_pktmbuf_prefree_seg(txep[0].mbuf);
             #  #  #  # ]
     353   [ #  #  #  #  :          0 :         if (likely(m)) {
             #  #  #  # ]
     354                 :          0 :                 free[0] = m;
     355                 :            :                 nb_free = 1;
     356   [ #  #  #  #  :          0 :                 for (uint32_t i = 1; i < n; i++) {
             #  #  #  # ]
     357   [ #  #  #  #  :          0 :                         m = rte_pktmbuf_prefree_seg(txep[i].mbuf);
             #  #  #  # ]
     358   [ #  #  #  #  :          0 :                         if (likely(m)) {
             #  #  #  # ]
     359   [ #  #  #  #  :          0 :                                 if (likely(m->pool == free[0]->pool)) {
             #  #  #  # ]
     360                 :          0 :                                         free[nb_free++] = m;
     361                 :            :                                 } else {
     362   [ #  #  #  #  :          0 :                                         rte_mbuf_raw_free_bulk(free[0]->pool, free, nb_free);
             #  #  #  # ]
     363                 :          0 :                                         free[0] = m;
     364                 :            :                                         nb_free = 1;
     365                 :            :                                 }
     366                 :            :                         }
     367                 :            :                 }
     368   [ #  #  #  #  :          0 :                 rte_mbuf_raw_free_bulk(free[0]->pool, free, nb_free);
             #  #  #  # ]
     369                 :            :         } else {
     370   [ #  #  #  #  :          0 :                 for (uint32_t i = 1; i < n; i++) {
             #  #  #  # ]
     371   [ #  #  #  #  :          0 :                         m = rte_pktmbuf_prefree_seg(txep[i].mbuf);
             #  #  #  # ]
     372                 :            :                         if (m)
     373   [ #  #  #  #  :          0 :                                 rte_mempool_put(m->pool, m);
             #  #  #  # ]
     374                 :            :                 }
     375                 :            :         }
     376                 :            : 
     377                 :          0 : done:
     378                 :            :         /* buffers were freed, update counters */
     379                 :          0 :         txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh);
     380                 :          0 :         txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh);
     381   [ #  #  #  #  :          0 :         if (txq->tx_next_dd >= txq->nb_tx_desc)
             #  #  #  # ]
     382                 :          0 :                 txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1);
     383                 :            : 
     384         [ #  # ]:          0 :         return txq->tx_rs_thresh;
     385                 :            : }
     386                 :            : 
     387                 :            : static inline void
     388                 :          0 : ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
     389                 :            : {
     390   [ #  #  #  # ]:          0 :         if (unlikely(!txq || !txq->sw_ring))
     391                 :            :                 return;
     392                 :            : 
     393         [ #  # ]:          0 :         if (!txq->use_vec_entry) {
     394                 :            :                 /* Free mbufs from (last_desc_cleaned + 1) to (tx_tail - 1). */
     395                 :          0 :                 const uint16_t start = (txq->last_desc_cleaned + 1) % txq->nb_tx_desc;
     396                 :            :                 const uint16_t nb_desc = txq->nb_tx_desc;
     397                 :          0 :                 const uint16_t end = txq->tx_tail;
     398                 :            : 
     399                 :            :                 uint16_t i = start;
     400         [ #  # ]:          0 :                 if (end < i) {
     401         [ #  # ]:          0 :                         for (; i < nb_desc; i++)
     402         [ #  # ]:          0 :                                 if (txq->sw_ring[i].mbuf != NULL)
     403                 :            :                                         rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
     404                 :            :                         i = 0;
     405                 :            :                 }
     406         [ #  # ]:          0 :                 for (; i < end; i++)
     407         [ #  # ]:          0 :                         if (txq->sw_ring[i].mbuf != NULL)
     408                 :            :                                 rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
     409                 :          0 :                 memset(txq->sw_ring, 0, sizeof(txq->sw_ring[0]) * nb_desc);
     410                 :          0 :                 return;
     411                 :            :         }
     412                 :            : 
     413                 :            :         /**
     414                 :            :          *  Vector and simple paths use sw_ring_vec (ci_tx_entry_vec).
     415                 :            :          *  vPMD tx will not set sw_ring's mbuf to NULL after free,
     416                 :            :          *  so determining buffers to free is a little more complex.
     417                 :            :          */
     418                 :          0 :         const uint16_t start = (txq->tx_next_dd - txq->tx_rs_thresh + 1) >> use_ctx;
     419                 :          0 :         const uint16_t nb_desc = txq->nb_tx_desc >> use_ctx;
     420                 :          0 :         const uint16_t end = txq->tx_tail >> use_ctx;
     421                 :            : 
     422                 :            :         uint16_t i = start;
     423         [ #  # ]:          0 :         if (end < i) {
     424         [ #  # ]:          0 :                 for (; i < nb_desc; i++)
     425                 :          0 :                         rte_pktmbuf_free_seg(txq->sw_ring_vec[i].mbuf);
     426                 :            :                 i = 0;
     427                 :            :         }
     428         [ #  # ]:          0 :         for (; i < end; i++)
     429                 :          0 :                 rte_pktmbuf_free_seg(txq->sw_ring_vec[i].mbuf);
     430                 :          0 :         memset(txq->sw_ring_vec, 0, sizeof(txq->sw_ring_vec[0]) * nb_desc);
     431                 :            : }
     432                 :            : 
     433                 :            : /**
     434                 :            :  * Select the best matching Tx path based on features
     435                 :            :  *
     436                 :            :  * @param req_features
     437                 :            :  *   The requested features for the Tx path
     438                 :            :  * @param infos
     439                 :            :  *   Array of information about the available Tx paths
     440                 :            :  * @param num_paths
     441                 :            :  *   Number of available paths in the infos array
     442                 :            :  * @param default_path
     443                 :            :  *   Index of the default path to use if no suitable path is found
     444                 :            :  * @param force_ctx
     445                 :            :  *   If true, only paths that support context descriptors may be selected.
     446                 :            :  *   Use this for offloads that require a context descriptor but cannot be
     447                 :            :  *   discovered purely from req_features->tx_offloads (e.g. a driver-specific
     448                 :            :  *   devarg, or a runtime/hardware-negotiated tag placement).
     449                 :            :  *
     450                 :            :  * @return
     451                 :            :  *   The packet burst function index that best matches the requested features,
     452                 :            :  *   or default_path if no suitable path is found
     453                 :            :  */
     454                 :            : static inline int
     455                 :          0 : ci_tx_path_select(const struct ci_tx_path_features *req_features,
     456                 :            :                         const struct ci_tx_path_info *infos,
     457                 :            :                         size_t num_paths,
     458                 :            :                         int default_path,
     459                 :            :                         bool force_ctx)
     460                 :            : {
     461                 :            :         int idx = default_path;
     462                 :            :         const struct ci_tx_path_features *chosen_path_features = NULL;
     463                 :            :         bool chosen_supports_ctx = false;
     464                 :            : 
     465         [ #  # ]:          0 :         for (unsigned int i = 0; i < num_paths; i++) {
     466                 :          0 :                 const struct ci_tx_path_features *path_features = &infos[i].features;
     467                 :            : 
     468                 :            :                 /* Do not select a path with a NULL pkt_burst function. */
     469         [ #  # ]:          0 :                 if (infos[i].pkt_burst == NULL)
     470                 :          0 :                         continue;
     471                 :            : 
     472                 :            :                 /* Do not select a disabled tx path. */
     473         [ #  # ]:          0 :                 if (path_features->disabled)
     474                 :          0 :                         continue;
     475                 :            : 
     476                 :            :                 /* Do not use a simple tx path if not requested. */
     477   [ #  #  #  # ]:          0 :                 if (path_features->simple_tx && !req_features->simple_tx)
     478                 :          0 :                         continue;
     479                 :            : 
     480                 :            :                 /* If a context descriptor is required, ensure the path supports it. */
     481   [ #  #  #  # ]:          0 :                 if (!infos[i].supports_ctx && force_ctx)
     482                 :          0 :                         continue;
     483                 :            : 
     484                 :            :                 /* If requested, ensure the path supports single queue TX. */
     485         [ #  # ]:          0 :                 if (path_features->single_queue != req_features->single_queue)
     486                 :          0 :                         continue;
     487                 :            : 
     488                 :            :                 /* Ensure the path supports the requested TX offloads. */
     489         [ #  # ]:          0 :                 if ((path_features->tx_offloads & req_features->tx_offloads) !=
     490                 :            :                                 req_features->tx_offloads)
     491                 :          0 :                         continue;
     492                 :            : 
     493                 :            :                 /* Ensure the path's SIMD width is compatible with the requested width. */
     494         [ #  # ]:          0 :                 if (path_features->simd_width > req_features->simd_width)
     495                 :          0 :                         continue;
     496                 :            : 
     497                 :            :                 /* Do not select the path if it is less suitable than the chosen path. */
     498         [ #  # ]:          0 :                 if (chosen_path_features != NULL) {
     499                 :            :                         /* Do not select paths with lower SIMD width than the chosen path. */
     500         [ #  # ]:          0 :                         if (path_features->simd_width < chosen_path_features->simd_width)
     501                 :          0 :                                 continue;
     502                 :            :                         /* The following tie-breaks only matter when SIMD widths are tied;
     503                 :            :                          * a strictly wider path is always preferred regardless of offload
     504                 :            :                          * count or ctx-descriptor use.
     505                 :            :                          */
     506         [ #  # ]:          0 :                         if (path_features->simd_width == chosen_path_features->simd_width) {
     507                 :            :                                 /* Do not select paths with more offloads enabled than the
     508                 :            :                                  * chosen path.
     509                 :            :                                  */
     510                 :          0 :                                 if (rte_popcount32(path_features->tx_offloads) >
     511         [ #  # ]:          0 :                                                 rte_popcount32(chosen_path_features->tx_offloads))
     512                 :          0 :                                         continue;
     513                 :            : 
     514                 :            :                                 /* Don't use a context descriptor unless necessary */
     515   [ #  #  #  # ]:          0 :                                 if (infos[i].supports_ctx && !chosen_supports_ctx)
     516                 :          0 :                                         continue;
     517                 :            :                         }
     518                 :            :                 }
     519                 :            : 
     520                 :            :                 /* Finally, select the path since it has met all the requirements. */
     521                 :          0 :                 idx = i;
     522                 :          0 :                 chosen_path_features = &infos[idx].features;
     523                 :          0 :                 chosen_supports_ctx = infos[idx].supports_ctx;
     524                 :            :         }
     525                 :            : 
     526                 :          0 :         return idx;
     527                 :            : }
     528                 :            : 
     529                 :            : /* include the scalar functions at the end, so they can use the common definitions.
     530                 :            :  * This is done so drivers can use all functions just by including tx.h
     531                 :            :  */
     532                 :            : #include "tx_scalar.h"
     533                 :            : 
     534                 :            : #endif /* _COMMON_INTEL_TX_H_ */

Generated by: LCOV version 1.14