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_ */
|