1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
9 #define NIX_TX_OFFLOAD_NONE (0)
10 #define NIX_TX_OFFLOAD_L3_L4_CSUM_F BIT(0)
11 #define NIX_TX_OFFLOAD_OL3_OL4_CSUM_F BIT(1)
12 #define NIX_TX_OFFLOAD_VLAN_QINQ_F BIT(2)
13 #define NIX_TX_OFFLOAD_MBUF_NOFF_F BIT(3)
14 #define NIX_TX_OFFLOAD_TSO_F BIT(4)
15 #define NIX_TX_OFFLOAD_TSTAMP_F BIT(5)
17 /* Flags to control xmit_prepare function.
18 * Defining it from backwards to denote its been
19 * not used as offload flags to pick function
21 #define NIX_TX_MULTI_SEG_F BIT(15)
23 #define NIX_TX_NEED_SEND_HDR_W1 \
24 (NIX_TX_OFFLOAD_L3_L4_CSUM_F | NIX_TX_OFFLOAD_OL3_OL4_CSUM_F | \
25 NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSO_F)
27 #define NIX_TX_NEED_EXT_HDR \
28 (NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSTAMP_F | \
31 #define NIX_XMIT_FC_OR_RETURN(txq, pkts) \
33 /* Cached value is low, Update the fc_cache_pkts */ \
34 if (unlikely((txq)->fc_cache_pkts < (pkts))) { \
35 /* Multiply with sqe_per_sqb to express in pkts */ \
36 (txq)->fc_cache_pkts = \
37 ((txq)->nb_sqb_bufs_adj - *(txq)->fc_mem) \
38 << (txq)->sqes_per_sqb_log2; \
39 /* Check it again for the room */ \
40 if (unlikely((txq)->fc_cache_pkts < (pkts))) \
45 /* Function to determine no of tx subdesc required in case ext
46 * sub desc is enabled.
48 static __rte_always_inline int
49 cn9k_nix_tx_ext_subs(const uint16_t flags)
51 return (flags & NIX_TX_OFFLOAD_TSTAMP_F)
54 (NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSO_F))
59 static __rte_always_inline void
60 cn9k_nix_xmit_prepare_tso(struct rte_mbuf *m, const uint64_t flags)
62 uint64_t mask, ol_flags = m->ol_flags;
64 if (flags & NIX_TX_OFFLOAD_TSO_F && (ol_flags & PKT_TX_TCP_SEG)) {
65 uintptr_t mdata = rte_pktmbuf_mtod(m, uintptr_t);
66 uint16_t *iplen, *oiplen, *oudplen;
67 uint16_t lso_sb, paylen;
69 mask = -!!(ol_flags & (PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IPV6));
70 lso_sb = (mask & (m->outer_l2_len + m->outer_l3_len)) +
71 m->l2_len + m->l3_len + m->l4_len;
73 /* Reduce payload len from base headers */
74 paylen = m->pkt_len - lso_sb;
76 /* Get iplen position assuming no tunnel hdr */
77 iplen = (uint16_t *)(mdata + m->l2_len +
78 (2 << !!(ol_flags & PKT_TX_IPV6)));
79 /* Handle tunnel tso */
80 if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) &&
81 (ol_flags & PKT_TX_TUNNEL_MASK)) {
82 const uint8_t is_udp_tun =
83 (CNXK_NIX_UDP_TUN_BITMASK >>
84 ((ol_flags & PKT_TX_TUNNEL_MASK) >> 45)) &
87 oiplen = (uint16_t *)(mdata + m->outer_l2_len +
90 *oiplen = rte_cpu_to_be_16(rte_be_to_cpu_16(*oiplen) -
93 /* Update format for UDP tunneled packet */
95 oudplen = (uint16_t *)(mdata + m->outer_l2_len +
97 *oudplen = rte_cpu_to_be_16(
98 rte_be_to_cpu_16(*oudplen) - paylen);
101 /* Update iplen position to inner ip hdr */
102 iplen = (uint16_t *)(mdata + lso_sb - m->l3_len -
104 (2 << !!(ol_flags & PKT_TX_IPV6)));
107 *iplen = rte_cpu_to_be_16(rte_be_to_cpu_16(*iplen) - paylen);
111 static __rte_always_inline void
112 cn9k_nix_xmit_prepare(struct rte_mbuf *m, uint64_t *cmd, const uint16_t flags,
113 const uint64_t lso_tun_fmt)
115 struct nix_send_ext_s *send_hdr_ext;
116 struct nix_send_hdr_s *send_hdr;
117 uint64_t ol_flags = 0, mask;
118 union nix_send_hdr_w1_u w1;
119 union nix_send_sg_s *sg;
121 send_hdr = (struct nix_send_hdr_s *)cmd;
122 if (flags & NIX_TX_NEED_EXT_HDR) {
123 send_hdr_ext = (struct nix_send_ext_s *)(cmd + 2);
124 sg = (union nix_send_sg_s *)(cmd + 4);
125 /* Clear previous markings */
126 send_hdr_ext->w0.lso = 0;
127 send_hdr_ext->w1.u = 0;
129 sg = (union nix_send_sg_s *)(cmd + 2);
132 if (flags & NIX_TX_NEED_SEND_HDR_W1) {
133 ol_flags = m->ol_flags;
137 if (!(flags & NIX_TX_MULTI_SEG_F)) {
138 send_hdr->w0.total = m->data_len;
140 roc_npa_aura_handle_to_aura(m->pool->pool_id);
145 * 3 => IPV4 with csum
147 * L3type and L3ptr needs to be set for either
148 * L3 csum or L4 csum or LSO
152 if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) &&
153 (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) {
154 const uint8_t csum = !!(ol_flags & PKT_TX_OUTER_UDP_CKSUM);
155 const uint8_t ol3type =
156 ((!!(ol_flags & PKT_TX_OUTER_IPV4)) << 1) +
157 ((!!(ol_flags & PKT_TX_OUTER_IPV6)) << 2) +
158 !!(ol_flags & PKT_TX_OUTER_IP_CKSUM);
161 w1.ol3type = ol3type;
162 mask = 0xffffull << ((!!ol3type) << 4);
163 w1.ol3ptr = ~mask & m->outer_l2_len;
164 w1.ol4ptr = ~mask & (w1.ol3ptr + m->outer_l3_len);
167 w1.ol4type = csum + (csum << 1);
170 w1.il3type = ((!!(ol_flags & PKT_TX_IPV4)) << 1) +
171 ((!!(ol_flags & PKT_TX_IPV6)) << 2);
172 w1.il3ptr = w1.ol4ptr + m->l2_len;
173 w1.il4ptr = w1.il3ptr + m->l3_len;
174 /* Increment it by 1 if it is IPV4 as 3 is with csum */
175 w1.il3type = w1.il3type + !!(ol_flags & PKT_TX_IP_CKSUM);
178 w1.il4type = (ol_flags & PKT_TX_L4_MASK) >> 52;
180 /* In case of no tunnel header use only
181 * shift IL3/IL4 fields a bit to use
182 * OL3/OL4 for header checksum
185 w1.u = ((w1.u & 0xFFFFFFFF00000000) >> (mask << 3)) |
186 ((w1.u & 0X00000000FFFFFFFF) >> (mask << 4));
188 } else if (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) {
189 const uint8_t csum = !!(ol_flags & PKT_TX_OUTER_UDP_CKSUM);
190 const uint8_t outer_l2_len = m->outer_l2_len;
193 w1.ol3ptr = outer_l2_len;
194 w1.ol4ptr = outer_l2_len + m->outer_l3_len;
195 /* Increment it by 1 if it is IPV4 as 3 is with csum */
196 w1.ol3type = ((!!(ol_flags & PKT_TX_OUTER_IPV4)) << 1) +
197 ((!!(ol_flags & PKT_TX_OUTER_IPV6)) << 2) +
198 !!(ol_flags & PKT_TX_OUTER_IP_CKSUM);
201 w1.ol4type = csum + (csum << 1);
203 } else if (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) {
204 const uint8_t l2_len = m->l2_len;
206 /* Always use OLXPTR and OLXTYPE when only
207 * when one header is present
212 w1.ol4ptr = l2_len + m->l3_len;
213 /* Increment it by 1 if it is IPV4 as 3 is with csum */
214 w1.ol3type = ((!!(ol_flags & PKT_TX_IPV4)) << 1) +
215 ((!!(ol_flags & PKT_TX_IPV6)) << 2) +
216 !!(ol_flags & PKT_TX_IP_CKSUM);
219 w1.ol4type = (ol_flags & PKT_TX_L4_MASK) >> 52;
222 if (flags & NIX_TX_NEED_EXT_HDR && flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
223 send_hdr_ext->w1.vlan1_ins_ena = !!(ol_flags & PKT_TX_VLAN);
224 /* HW will update ptr after vlan0 update */
225 send_hdr_ext->w1.vlan1_ins_ptr = 12;
226 send_hdr_ext->w1.vlan1_ins_tci = m->vlan_tci;
228 send_hdr_ext->w1.vlan0_ins_ena = !!(ol_flags & PKT_TX_QINQ);
229 /* 2B before end of l2 header */
230 send_hdr_ext->w1.vlan0_ins_ptr = 12;
231 send_hdr_ext->w1.vlan0_ins_tci = m->vlan_tci_outer;
234 if (flags & NIX_TX_OFFLOAD_TSO_F && (ol_flags & PKT_TX_TCP_SEG)) {
238 mask = -(!w1.il3type);
239 lso_sb = (mask & w1.ol4ptr) + (~mask & w1.il4ptr) + m->l4_len;
241 send_hdr_ext->w0.lso_sb = lso_sb;
242 send_hdr_ext->w0.lso = 1;
243 send_hdr_ext->w0.lso_mps = m->tso_segsz;
244 send_hdr_ext->w0.lso_format =
245 NIX_LSO_FORMAT_IDX_TSOV4 + !!(ol_flags & PKT_TX_IPV6);
246 w1.ol4type = NIX_SENDL4TYPE_TCP_CKSUM;
248 /* Handle tunnel tso */
249 if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) &&
250 (ol_flags & PKT_TX_TUNNEL_MASK)) {
251 const uint8_t is_udp_tun =
252 (CNXK_NIX_UDP_TUN_BITMASK >>
253 ((ol_flags & PKT_TX_TUNNEL_MASK) >> 45)) &
255 uint8_t shift = is_udp_tun ? 32 : 0;
257 shift += (!!(ol_flags & PKT_TX_OUTER_IPV6) << 4);
258 shift += (!!(ol_flags & PKT_TX_IPV6) << 3);
260 w1.il4type = NIX_SENDL4TYPE_TCP_CKSUM;
261 w1.ol4type = is_udp_tun ? NIX_SENDL4TYPE_UDP_CKSUM : 0;
262 /* Update format for UDP tunneled packet */
263 send_hdr_ext->w0.lso_format = (lso_tun_fmt >> shift);
267 if (flags & NIX_TX_NEED_SEND_HDR_W1)
268 send_hdr->w1.u = w1.u;
270 if (!(flags & NIX_TX_MULTI_SEG_F)) {
271 sg->seg1_size = m->data_len;
272 *(rte_iova_t *)(++sg) = rte_mbuf_data_iova(m);
274 if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
275 /* DF bit = 1 if refcount of current mbuf or parent mbuf
277 * DF bit = 0 otherwise
279 send_hdr->w0.df = cnxk_nix_prefree_seg(m);
280 /* Ensuring mbuf fields which got updated in
281 * cnxk_nix_prefree_seg are written before LMTST.
285 /* Mark mempool object as "put" since it is freed by NIX */
286 if (!send_hdr->w0.df)
287 __mempool_check_cookies(m->pool, (void **)&m, 1, 0);
291 static __rte_always_inline void
292 cn9k_nix_xmit_prepare_tstamp(uint64_t *cmd, const uint64_t *send_mem_desc,
293 const uint64_t ol_flags, const uint16_t no_segdw,
294 const uint16_t flags)
296 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
297 struct nix_send_mem_s *send_mem;
298 uint16_t off = (no_segdw - 1) << 1;
299 const uint8_t is_ol_tstamp = !(ol_flags & PKT_TX_IEEE1588_TMST);
301 send_mem = (struct nix_send_mem_s *)(cmd + off);
302 if (flags & NIX_TX_MULTI_SEG_F) {
303 /* Retrieving the default desc values */
304 cmd[off] = send_mem_desc[6];
306 /* Using compiler barier to avoid voilation of C
309 rte_compiler_barrier();
312 /* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
313 * should not be recorded, hence changing the alg type to
314 * NIX_SENDMEMALG_SET and also changing send mem addr field to
315 * next 8 bytes as it corrpt the actual tx tstamp registered
318 send_mem->w0.cn9k.alg =
319 NIX_SENDMEMALG_SETTSTMP - (is_ol_tstamp);
321 send_mem->addr = (rte_iova_t)((uint64_t *)send_mem_desc[7] +
326 static __rte_always_inline void
327 cn9k_nix_xmit_one(uint64_t *cmd, void *lmt_addr, const rte_iova_t io_addr,
328 const uint32_t flags)
333 roc_lmt_mov(lmt_addr, cmd, cn9k_nix_tx_ext_subs(flags));
334 lmt_status = roc_lmt_submit_ldeor(io_addr);
335 } while (lmt_status == 0);
338 static __rte_always_inline void
339 cn9k_nix_xmit_prep_lmt(uint64_t *cmd, void *lmt_addr, const uint32_t flags)
341 roc_lmt_mov(lmt_addr, cmd, cn9k_nix_tx_ext_subs(flags));
344 static __rte_always_inline uint64_t
345 cn9k_nix_xmit_submit_lmt(const rte_iova_t io_addr)
347 return roc_lmt_submit_ldeor(io_addr);
350 static __rte_always_inline uint64_t
351 cn9k_nix_xmit_submit_lmt_release(const rte_iova_t io_addr)
353 return roc_lmt_submit_ldeorl(io_addr);
356 static __rte_always_inline uint16_t
357 cn9k_nix_prepare_mseg(struct rte_mbuf *m, uint64_t *cmd, const uint16_t flags)
359 struct nix_send_hdr_s *send_hdr;
360 union nix_send_sg_s *sg;
361 struct rte_mbuf *m_next;
362 uint64_t *slist, sg_u;
367 send_hdr = (struct nix_send_hdr_s *)cmd;
368 send_hdr->w0.total = m->pkt_len;
369 send_hdr->w0.aura = roc_npa_aura_handle_to_aura(m->pool->pool_id);
371 if (flags & NIX_TX_NEED_EXT_HDR)
376 sg = (union nix_send_sg_s *)&cmd[2 + off];
377 /* Clear sg->u header before use */
378 sg->u &= 0xFC00000000000000;
380 slist = &cmd[3 + off];
383 nb_segs = m->nb_segs;
385 /* Fill mbuf segments */
388 sg_u = sg_u | ((uint64_t)m->data_len << (i << 4));
389 *slist = rte_mbuf_data_iova(m);
390 /* Set invert df if buffer is not to be freed by H/W */
391 if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
392 sg_u |= (cnxk_nix_prefree_seg(m) << (i + 55));
393 /* Commit changes to mbuf */
396 /* Mark mempool object as "put" since it is freed by NIX */
397 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
398 if (!(sg_u & (1ULL << (i + 55))))
399 __mempool_check_cookies(m->pool, (void **)&m, 1, 0);
405 if (i > 2 && nb_segs) {
407 /* Next SG subdesc */
408 *(uint64_t *)slist = sg_u & 0xFC00000000000000;
411 sg = (union nix_send_sg_s *)slist;
420 segdw = (uint64_t *)slist - (uint64_t *)&cmd[2 + off];
421 /* Roundup extra dwords to multiple of 2 */
422 segdw = (segdw >> 1) + (segdw & 0x1);
424 segdw += (off >> 1) + 1 + !!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
425 send_hdr->w0.sizem1 = segdw - 1;
430 static __rte_always_inline void
431 cn9k_nix_xmit_mseg_prep_lmt(uint64_t *cmd, void *lmt_addr, uint16_t segdw)
433 roc_lmt_mov_seg(lmt_addr, (const void *)cmd, segdw);
436 static __rte_always_inline void
437 cn9k_nix_xmit_mseg_one(uint64_t *cmd, void *lmt_addr, rte_iova_t io_addr,
443 roc_lmt_mov_seg(lmt_addr, (const void *)cmd, segdw);
444 lmt_status = roc_lmt_submit_ldeor(io_addr);
445 } while (lmt_status == 0);
448 static __rte_always_inline void
449 cn9k_nix_xmit_mseg_one_release(uint64_t *cmd, void *lmt_addr,
450 rte_iova_t io_addr, uint16_t segdw)
456 roc_lmt_mov_seg(lmt_addr, (const void *)cmd, segdw);
457 lmt_status = roc_lmt_submit_ldeor(io_addr);
458 } while (lmt_status == 0);
461 static __rte_always_inline uint16_t
462 cn9k_nix_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts,
463 uint64_t *cmd, const uint16_t flags)
465 struct cn9k_eth_txq *txq = tx_queue;
466 const rte_iova_t io_addr = txq->io_addr;
467 void *lmt_addr = txq->lmt_addr;
468 uint64_t lso_tun_fmt;
471 NIX_XMIT_FC_OR_RETURN(txq, pkts);
473 roc_lmt_mov(cmd, &txq->cmd[0], cn9k_nix_tx_ext_subs(flags));
475 /* Perform header writes before barrier for TSO */
476 if (flags & NIX_TX_OFFLOAD_TSO_F) {
477 lso_tun_fmt = txq->lso_tun_fmt;
479 for (i = 0; i < pkts; i++)
480 cn9k_nix_xmit_prepare_tso(tx_pkts[i], flags);
483 /* Lets commit any changes in the packet here as no further changes
484 * to the packet will be done unless no fast free is enabled.
486 if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
489 for (i = 0; i < pkts; i++) {
490 cn9k_nix_xmit_prepare(tx_pkts[i], cmd, flags, lso_tun_fmt);
491 cn9k_nix_xmit_prepare_tstamp(cmd, &txq->cmd[0],
492 tx_pkts[i]->ol_flags, 4, flags);
493 cn9k_nix_xmit_one(cmd, lmt_addr, io_addr, flags);
496 /* Reduce the cached count */
497 txq->fc_cache_pkts -= pkts;
502 static __rte_always_inline uint16_t
503 cn9k_nix_xmit_pkts_mseg(void *tx_queue, struct rte_mbuf **tx_pkts,
504 uint16_t pkts, uint64_t *cmd, const uint16_t flags)
506 struct cn9k_eth_txq *txq = tx_queue;
507 const rte_iova_t io_addr = txq->io_addr;
508 void *lmt_addr = txq->lmt_addr;
509 uint64_t lso_tun_fmt;
513 NIX_XMIT_FC_OR_RETURN(txq, pkts);
515 roc_lmt_mov(cmd, &txq->cmd[0], cn9k_nix_tx_ext_subs(flags));
517 /* Perform header writes before barrier for TSO */
518 if (flags & NIX_TX_OFFLOAD_TSO_F) {
519 lso_tun_fmt = txq->lso_tun_fmt;
521 for (i = 0; i < pkts; i++)
522 cn9k_nix_xmit_prepare_tso(tx_pkts[i], flags);
525 /* Lets commit any changes in the packet here as no further changes
526 * to the packet will be done unless no fast free is enabled.
528 if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
531 for (i = 0; i < pkts; i++) {
532 cn9k_nix_xmit_prepare(tx_pkts[i], cmd, flags, lso_tun_fmt);
533 segdw = cn9k_nix_prepare_mseg(tx_pkts[i], cmd, flags);
534 cn9k_nix_xmit_prepare_tstamp(cmd, &txq->cmd[0],
535 tx_pkts[i]->ol_flags, segdw,
537 cn9k_nix_xmit_mseg_one(cmd, lmt_addr, io_addr, segdw);
540 /* Reduce the cached count */
541 txq->fc_cache_pkts -= pkts;
546 #if defined(RTE_ARCH_ARM64)
548 #define NIX_DESCS_PER_LOOP 4
549 static __rte_always_inline uint16_t
550 cn9k_nix_xmit_pkts_vector(void *tx_queue, struct rte_mbuf **tx_pkts,
551 uint16_t pkts, uint64_t *cmd, const uint16_t flags)
553 uint64x2_t dataoff_iova0, dataoff_iova1, dataoff_iova2, dataoff_iova3;
554 uint64x2_t len_olflags0, len_olflags1, len_olflags2, len_olflags3;
555 uint64x2_t cmd0[NIX_DESCS_PER_LOOP], cmd1[NIX_DESCS_PER_LOOP],
556 cmd2[NIX_DESCS_PER_LOOP], cmd3[NIX_DESCS_PER_LOOP];
557 uint64_t *mbuf0, *mbuf1, *mbuf2, *mbuf3;
558 uint64x2_t senddesc01_w0, senddesc23_w0;
559 uint64x2_t senddesc01_w1, senddesc23_w1;
560 uint64x2_t sendext01_w0, sendext23_w0;
561 uint64x2_t sendext01_w1, sendext23_w1;
562 uint64x2_t sendmem01_w0, sendmem23_w0;
563 uint64x2_t sendmem01_w1, sendmem23_w1;
564 uint64x2_t sgdesc01_w0, sgdesc23_w0;
565 uint64x2_t sgdesc01_w1, sgdesc23_w1;
566 struct cn9k_eth_txq *txq = tx_queue;
567 uint64_t *lmt_addr = txq->lmt_addr;
568 rte_iova_t io_addr = txq->io_addr;
569 uint64x2_t ltypes01, ltypes23;
570 uint64x2_t xtmp128, ytmp128;
571 uint64x2_t xmask01, xmask23;
572 uint64_t lmt_status, i;
575 NIX_XMIT_FC_OR_RETURN(txq, pkts);
577 pkts_left = pkts & (NIX_DESCS_PER_LOOP - 1);
578 pkts = RTE_ALIGN_FLOOR(pkts, NIX_DESCS_PER_LOOP);
580 /* Reduce the cached count */
581 txq->fc_cache_pkts -= pkts;
583 /* Lets commit any changes in the packet here as no further changes
584 * to the packet will be done unless no fast free is enabled.
586 if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
589 senddesc01_w0 = vld1q_dup_u64(&txq->cmd[0]);
590 senddesc23_w0 = senddesc01_w0;
591 senddesc01_w1 = vdupq_n_u64(0);
592 senddesc23_w1 = senddesc01_w1;
594 /* Load command defaults into vector variables. */
595 if (flags & NIX_TX_NEED_EXT_HDR) {
596 sendext01_w0 = vld1q_dup_u64(&txq->cmd[2]);
597 sendext23_w0 = sendext01_w0;
598 sendext01_w1 = vdupq_n_u64(12 | 12U << 24);
599 sendext23_w1 = sendext01_w1;
600 sgdesc01_w0 = vld1q_dup_u64(&txq->cmd[4]);
601 sgdesc23_w0 = sgdesc01_w0;
602 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
603 sendmem01_w0 = vld1q_dup_u64(&txq->cmd[6]);
604 sendmem23_w0 = sendmem01_w0;
605 sendmem01_w1 = vld1q_dup_u64(&txq->cmd[7]);
606 sendmem23_w1 = sendmem01_w1;
609 sgdesc01_w0 = vld1q_dup_u64(&txq->cmd[2]);
610 sgdesc23_w0 = sgdesc01_w0;
613 for (i = 0; i < pkts; i += NIX_DESCS_PER_LOOP) {
614 /* Clear lower 32bit of SEND_HDR_W0 and SEND_SG_W0 */
616 vbicq_u64(senddesc01_w0, vdupq_n_u64(0xFFFFFFFF));
617 sgdesc01_w0 = vbicq_u64(sgdesc01_w0, vdupq_n_u64(0xFFFFFFFF));
619 senddesc23_w0 = senddesc01_w0;
620 sgdesc23_w0 = sgdesc01_w0;
622 /* Clear vlan enables. */
623 if (flags & NIX_TX_NEED_EXT_HDR) {
624 sendext01_w1 = vbicq_u64(sendext01_w1,
625 vdupq_n_u64(0x3FFFF00FFFF00));
626 sendext23_w1 = sendext01_w1;
629 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
630 /* Reset send mem alg to SETTSTMP from SUB*/
631 sendmem01_w0 = vbicq_u64(sendmem01_w0,
632 vdupq_n_u64(BIT_ULL(59)));
633 /* Reset send mem address to default. */
635 vbicq_u64(sendmem01_w1, vdupq_n_u64(0xF));
636 sendmem23_w0 = sendmem01_w0;
637 sendmem23_w1 = sendmem01_w1;
640 /* Move mbufs to iova */
641 mbuf0 = (uint64_t *)tx_pkts[0];
642 mbuf1 = (uint64_t *)tx_pkts[1];
643 mbuf2 = (uint64_t *)tx_pkts[2];
644 mbuf3 = (uint64_t *)tx_pkts[3];
646 mbuf0 = (uint64_t *)((uintptr_t)mbuf0 +
647 offsetof(struct rte_mbuf, buf_iova));
648 mbuf1 = (uint64_t *)((uintptr_t)mbuf1 +
649 offsetof(struct rte_mbuf, buf_iova));
650 mbuf2 = (uint64_t *)((uintptr_t)mbuf2 +
651 offsetof(struct rte_mbuf, buf_iova));
652 mbuf3 = (uint64_t *)((uintptr_t)mbuf3 +
653 offsetof(struct rte_mbuf, buf_iova));
655 * Get mbuf's, olflags, iova, pktlen, dataoff
656 * dataoff_iovaX.D[0] = iova,
657 * dataoff_iovaX.D[1](15:0) = mbuf->dataoff
658 * len_olflagsX.D[0] = ol_flags,
659 * len_olflagsX.D[1](63:32) = mbuf->pkt_len
661 dataoff_iova0 = vld1q_u64(mbuf0);
662 len_olflags0 = vld1q_u64(mbuf0 + 2);
663 dataoff_iova1 = vld1q_u64(mbuf1);
664 len_olflags1 = vld1q_u64(mbuf1 + 2);
665 dataoff_iova2 = vld1q_u64(mbuf2);
666 len_olflags2 = vld1q_u64(mbuf2 + 2);
667 dataoff_iova3 = vld1q_u64(mbuf3);
668 len_olflags3 = vld1q_u64(mbuf3 + 2);
670 /* Move mbufs to point pool */
671 mbuf0 = (uint64_t *)((uintptr_t)mbuf0 +
672 offsetof(struct rte_mbuf, pool) -
673 offsetof(struct rte_mbuf, buf_iova));
674 mbuf1 = (uint64_t *)((uintptr_t)mbuf1 +
675 offsetof(struct rte_mbuf, pool) -
676 offsetof(struct rte_mbuf, buf_iova));
677 mbuf2 = (uint64_t *)((uintptr_t)mbuf2 +
678 offsetof(struct rte_mbuf, pool) -
679 offsetof(struct rte_mbuf, buf_iova));
680 mbuf3 = (uint64_t *)((uintptr_t)mbuf3 +
681 offsetof(struct rte_mbuf, pool) -
682 offsetof(struct rte_mbuf, buf_iova));
684 if (flags & (NIX_TX_OFFLOAD_OL3_OL4_CSUM_F |
685 NIX_TX_OFFLOAD_L3_L4_CSUM_F)) {
686 /* Get tx_offload for ol2, ol3, l2, l3 lengths */
688 * E(8):OL2_LEN(7):OL3_LEN(9):E(24):L3_LEN(9):L2_LEN(7)
689 * E(8):OL2_LEN(7):OL3_LEN(9):E(24):L3_LEN(9):L2_LEN(7)
692 asm volatile("LD1 {%[a].D}[0],[%[in]]\n\t"
693 : [a] "+w"(senddesc01_w1)
694 : [in] "r"(mbuf0 + 2)
697 asm volatile("LD1 {%[a].D}[1],[%[in]]\n\t"
698 : [a] "+w"(senddesc01_w1)
699 : [in] "r"(mbuf1 + 2)
702 asm volatile("LD1 {%[b].D}[0],[%[in]]\n\t"
703 : [b] "+w"(senddesc23_w1)
704 : [in] "r"(mbuf2 + 2)
707 asm volatile("LD1 {%[b].D}[1],[%[in]]\n\t"
708 : [b] "+w"(senddesc23_w1)
709 : [in] "r"(mbuf3 + 2)
712 /* Get pool pointer alone */
713 mbuf0 = (uint64_t *)*mbuf0;
714 mbuf1 = (uint64_t *)*mbuf1;
715 mbuf2 = (uint64_t *)*mbuf2;
716 mbuf3 = (uint64_t *)*mbuf3;
718 /* Get pool pointer alone */
719 mbuf0 = (uint64_t *)*mbuf0;
720 mbuf1 = (uint64_t *)*mbuf1;
721 mbuf2 = (uint64_t *)*mbuf2;
722 mbuf3 = (uint64_t *)*mbuf3;
725 const uint8x16_t shuf_mask2 = {
726 0x4, 0x5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
727 0xc, 0xd, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
729 xtmp128 = vzip2q_u64(len_olflags0, len_olflags1);
730 ytmp128 = vzip2q_u64(len_olflags2, len_olflags3);
732 /* Clear dataoff_iovaX.D[1] bits other than dataoff(15:0) */
733 const uint64x2_t and_mask0 = {
738 dataoff_iova0 = vandq_u64(dataoff_iova0, and_mask0);
739 dataoff_iova1 = vandq_u64(dataoff_iova1, and_mask0);
740 dataoff_iova2 = vandq_u64(dataoff_iova2, and_mask0);
741 dataoff_iova3 = vandq_u64(dataoff_iova3, and_mask0);
744 * Pick only 16 bits of pktlen preset at bits 63:32
745 * and place them at bits 15:0.
747 xtmp128 = vqtbl1q_u8(xtmp128, shuf_mask2);
748 ytmp128 = vqtbl1q_u8(ytmp128, shuf_mask2);
750 /* Add pairwise to get dataoff + iova in sgdesc_w1 */
751 sgdesc01_w1 = vpaddq_u64(dataoff_iova0, dataoff_iova1);
752 sgdesc23_w1 = vpaddq_u64(dataoff_iova2, dataoff_iova3);
754 /* Orr both sgdesc_w0 and senddesc_w0 with 16 bits of
755 * pktlen at 15:0 position.
757 sgdesc01_w0 = vorrq_u64(sgdesc01_w0, xtmp128);
758 sgdesc23_w0 = vorrq_u64(sgdesc23_w0, ytmp128);
759 senddesc01_w0 = vorrq_u64(senddesc01_w0, xtmp128);
760 senddesc23_w0 = vorrq_u64(senddesc23_w0, ytmp128);
762 /* Move mbuf to point to pool_id. */
763 mbuf0 = (uint64_t *)((uintptr_t)mbuf0 +
764 offsetof(struct rte_mempool, pool_id));
765 mbuf1 = (uint64_t *)((uintptr_t)mbuf1 +
766 offsetof(struct rte_mempool, pool_id));
767 mbuf2 = (uint64_t *)((uintptr_t)mbuf2 +
768 offsetof(struct rte_mempool, pool_id));
769 mbuf3 = (uint64_t *)((uintptr_t)mbuf3 +
770 offsetof(struct rte_mempool, pool_id));
772 if ((flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
773 !(flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
775 * Lookup table to translate ol_flags to
776 * il3/il4 types. But we still use ol3/ol4 types in
777 * senddesc_w1 as only one header processing is enabled.
779 const uint8x16_t tbl = {
780 /* [0-15] = il4type:il3type */
781 0x04, /* none (IPv6 assumed) */
782 0x14, /* PKT_TX_TCP_CKSUM (IPv6 assumed) */
783 0x24, /* PKT_TX_SCTP_CKSUM (IPv6 assumed) */
784 0x34, /* PKT_TX_UDP_CKSUM (IPv6 assumed) */
785 0x03, /* PKT_TX_IP_CKSUM */
786 0x13, /* PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM */
787 0x23, /* PKT_TX_IP_CKSUM | PKT_TX_SCTP_CKSUM */
788 0x33, /* PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM */
789 0x02, /* PKT_TX_IPV4 */
790 0x12, /* PKT_TX_IPV4 | PKT_TX_TCP_CKSUM */
791 0x22, /* PKT_TX_IPV4 | PKT_TX_SCTP_CKSUM */
792 0x32, /* PKT_TX_IPV4 | PKT_TX_UDP_CKSUM */
793 0x03, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM */
794 0x13, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
797 0x23, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
800 0x33, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
805 /* Extract olflags to translate to iltypes */
806 xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
807 ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
810 * E(47):L3_LEN(9):L2_LEN(7+z)
811 * E(47):L3_LEN(9):L2_LEN(7+z)
813 senddesc01_w1 = vshlq_n_u64(senddesc01_w1, 1);
814 senddesc23_w1 = vshlq_n_u64(senddesc23_w1, 1);
816 /* Move OLFLAGS bits 55:52 to 51:48
817 * with zeros preprended on the byte and rest
820 xtmp128 = vshrq_n_u8(xtmp128, 4);
821 ytmp128 = vshrq_n_u8(ytmp128, 4);
823 * E(48):L3_LEN(8):L2_LEN(z+7)
824 * E(48):L3_LEN(8):L2_LEN(z+7)
826 const int8x16_t tshft3 = {
827 -1, 0, 8, 8, 8, 8, 8, 8,
828 -1, 0, 8, 8, 8, 8, 8, 8,
831 senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
832 senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
835 ltypes01 = vqtbl1q_u8(tbl, xtmp128);
836 ltypes23 = vqtbl1q_u8(tbl, ytmp128);
838 /* Pick only relevant fields i.e Bit 48:55 of iltype
839 * and place it in ol3/ol4type of senddesc_w1
841 const uint8x16_t shuf_mask0 = {
842 0xFF, 0xFF, 0xFF, 0xFF, 0x6, 0xFF, 0xFF, 0xFF,
843 0xFF, 0xFF, 0xFF, 0xFF, 0xE, 0xFF, 0xFF, 0xFF,
846 ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
847 ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
849 /* Prepare ol4ptr, ol3ptr from ol3len, ol2len.
850 * a [E(32):E(16):OL3(8):OL2(8)]
852 * a [E(32):E(16):(OL3+OL2):OL2]
853 * => E(32):E(16)::OL4PTR(8):OL3PTR(8)
855 senddesc01_w1 = vaddq_u8(senddesc01_w1,
856 vshlq_n_u16(senddesc01_w1, 8));
857 senddesc23_w1 = vaddq_u8(senddesc23_w1,
858 vshlq_n_u16(senddesc23_w1, 8));
860 /* Move ltypes to senddesc*_w1 */
861 senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
862 senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
863 } else if (!(flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
864 (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
866 * Lookup table to translate ol_flags to
870 const uint8x16_t tbl = {
871 /* [0-15] = ol4type:ol3type */
873 0x03, /* OUTER_IP_CKSUM */
874 0x02, /* OUTER_IPV4 */
875 0x03, /* OUTER_IPV4 | OUTER_IP_CKSUM */
876 0x04, /* OUTER_IPV6 */
877 0x00, /* OUTER_IPV6 | OUTER_IP_CKSUM */
878 0x00, /* OUTER_IPV6 | OUTER_IPV4 */
879 0x00, /* OUTER_IPV6 | OUTER_IPV4 |
882 0x00, /* OUTER_UDP_CKSUM */
883 0x33, /* OUTER_UDP_CKSUM | OUTER_IP_CKSUM */
884 0x32, /* OUTER_UDP_CKSUM | OUTER_IPV4 */
885 0x33, /* OUTER_UDP_CKSUM | OUTER_IPV4 |
888 0x34, /* OUTER_UDP_CKSUM | OUTER_IPV6 */
889 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
892 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
895 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
896 * OUTER_IPV4 | OUTER_IP_CKSUM
900 /* Extract olflags to translate to iltypes */
901 xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
902 ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
905 * E(47):OL3_LEN(9):OL2_LEN(7+z)
906 * E(47):OL3_LEN(9):OL2_LEN(7+z)
908 const uint8x16_t shuf_mask5 = {
909 0x6, 0x5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
910 0xE, 0xD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
912 senddesc01_w1 = vqtbl1q_u8(senddesc01_w1, shuf_mask5);
913 senddesc23_w1 = vqtbl1q_u8(senddesc23_w1, shuf_mask5);
915 /* Extract outer ol flags only */
916 const uint64x2_t o_cksum_mask = {
921 xtmp128 = vandq_u64(xtmp128, o_cksum_mask);
922 ytmp128 = vandq_u64(ytmp128, o_cksum_mask);
924 /* Extract OUTER_UDP_CKSUM bit 41 and
928 xtmp128 = xtmp128 | vshlq_n_u64(xtmp128, 20);
929 ytmp128 = ytmp128 | vshlq_n_u64(ytmp128, 20);
931 /* Shift oltype by 2 to start nibble from BIT(56)
934 xtmp128 = vshrq_n_u8(xtmp128, 2);
935 ytmp128 = vshrq_n_u8(ytmp128, 2);
937 * E(48):L3_LEN(8):L2_LEN(z+7)
938 * E(48):L3_LEN(8):L2_LEN(z+7)
940 const int8x16_t tshft3 = {
941 -1, 0, 8, 8, 8, 8, 8, 8,
942 -1, 0, 8, 8, 8, 8, 8, 8,
945 senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
946 senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
949 ltypes01 = vqtbl1q_u8(tbl, xtmp128);
950 ltypes23 = vqtbl1q_u8(tbl, ytmp128);
952 /* Pick only relevant fields i.e Bit 56:63 of oltype
953 * and place it in ol3/ol4type of senddesc_w1
955 const uint8x16_t shuf_mask0 = {
956 0xFF, 0xFF, 0xFF, 0xFF, 0x7, 0xFF, 0xFF, 0xFF,
957 0xFF, 0xFF, 0xFF, 0xFF, 0xF, 0xFF, 0xFF, 0xFF,
960 ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
961 ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
963 /* Prepare ol4ptr, ol3ptr from ol3len, ol2len.
964 * a [E(32):E(16):OL3(8):OL2(8)]
966 * a [E(32):E(16):(OL3+OL2):OL2]
967 * => E(32):E(16)::OL4PTR(8):OL3PTR(8)
969 senddesc01_w1 = vaddq_u8(senddesc01_w1,
970 vshlq_n_u16(senddesc01_w1, 8));
971 senddesc23_w1 = vaddq_u8(senddesc23_w1,
972 vshlq_n_u16(senddesc23_w1, 8));
974 /* Move ltypes to senddesc*_w1 */
975 senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
976 senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
977 } else if ((flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
978 (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
979 /* Lookup table to translate ol_flags to
980 * ol4type, ol3type, il4type, il3type of senddesc_w1
982 const uint8x16x2_t tbl = {{
984 /* [0-15] = il4type:il3type */
985 0x04, /* none (IPv6) */
986 0x14, /* PKT_TX_TCP_CKSUM (IPv6) */
987 0x24, /* PKT_TX_SCTP_CKSUM (IPv6) */
988 0x34, /* PKT_TX_UDP_CKSUM (IPv6) */
989 0x03, /* PKT_TX_IP_CKSUM */
990 0x13, /* PKT_TX_IP_CKSUM |
993 0x23, /* PKT_TX_IP_CKSUM |
996 0x33, /* PKT_TX_IP_CKSUM |
999 0x02, /* PKT_TX_IPV4 */
1000 0x12, /* PKT_TX_IPV4 |
1003 0x22, /* PKT_TX_IPV4 |
1006 0x32, /* PKT_TX_IPV4 |
1009 0x03, /* PKT_TX_IPV4 |
1012 0x13, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
1015 0x23, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
1018 0x33, /* PKT_TX_IPV4 | PKT_TX_IP_CKSUM |
1024 /* [16-31] = ol4type:ol3type */
1026 0x03, /* OUTER_IP_CKSUM */
1027 0x02, /* OUTER_IPV4 */
1028 0x03, /* OUTER_IPV4 | OUTER_IP_CKSUM */
1029 0x04, /* OUTER_IPV6 */
1030 0x00, /* OUTER_IPV6 | OUTER_IP_CKSUM */
1031 0x00, /* OUTER_IPV6 | OUTER_IPV4 */
1032 0x00, /* OUTER_IPV6 | OUTER_IPV4 |
1035 0x00, /* OUTER_UDP_CKSUM */
1036 0x33, /* OUTER_UDP_CKSUM |
1039 0x32, /* OUTER_UDP_CKSUM |
1042 0x33, /* OUTER_UDP_CKSUM |
1043 * OUTER_IPV4 | OUTER_IP_CKSUM
1045 0x34, /* OUTER_UDP_CKSUM |
1048 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
1051 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
1054 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
1055 * OUTER_IPV4 | OUTER_IP_CKSUM
1060 /* Extract olflags to translate to oltype & iltype */
1061 xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
1062 ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
1065 * E(8):OL2_LN(7):OL3_LN(9):E(23):L3_LN(9):L2_LN(7+z)
1066 * E(8):OL2_LN(7):OL3_LN(9):E(23):L3_LN(9):L2_LN(7+z)
1068 const uint32x4_t tshft_4 = {
1074 senddesc01_w1 = vshlq_u32(senddesc01_w1, tshft_4);
1075 senddesc23_w1 = vshlq_u32(senddesc23_w1, tshft_4);
1078 * E(32):L3_LEN(8):L2_LEN(7+Z):OL3_LEN(8):OL2_LEN(7+Z)
1079 * E(32):L3_LEN(8):L2_LEN(7+Z):OL3_LEN(8):OL2_LEN(7+Z)
1081 const uint8x16_t shuf_mask5 = {
1082 0x6, 0x5, 0x0, 0x1, 0xFF, 0xFF, 0xFF, 0xFF,
1083 0xE, 0xD, 0x8, 0x9, 0xFF, 0xFF, 0xFF, 0xFF,
1085 senddesc01_w1 = vqtbl1q_u8(senddesc01_w1, shuf_mask5);
1086 senddesc23_w1 = vqtbl1q_u8(senddesc23_w1, shuf_mask5);
1088 /* Extract outer and inner header ol_flags */
1089 const uint64x2_t oi_cksum_mask = {
1094 xtmp128 = vandq_u64(xtmp128, oi_cksum_mask);
1095 ytmp128 = vandq_u64(ytmp128, oi_cksum_mask);
1097 /* Extract OUTER_UDP_CKSUM bit 41 and
1101 xtmp128 = xtmp128 | vshlq_n_u64(xtmp128, 20);
1102 ytmp128 = ytmp128 | vshlq_n_u64(ytmp128, 20);
1104 /* Shift right oltype by 2 and iltype by 4
1105 * to start oltype nibble from BIT(58)
1106 * instead of BIT(56) and iltype nibble from BIT(48)
1107 * instead of BIT(52).
1109 const int8x16_t tshft5 = {
1110 8, 8, 8, 8, 8, 8, -4, -2,
1111 8, 8, 8, 8, 8, 8, -4, -2,
1114 xtmp128 = vshlq_u8(xtmp128, tshft5);
1115 ytmp128 = vshlq_u8(ytmp128, tshft5);
1117 * E(32):L3_LEN(8):L2_LEN(8):OL3_LEN(8):OL2_LEN(8)
1118 * E(32):L3_LEN(8):L2_LEN(8):OL3_LEN(8):OL2_LEN(8)
1120 const int8x16_t tshft3 = {
1121 -1, 0, -1, 0, 0, 0, 0, 0,
1122 -1, 0, -1, 0, 0, 0, 0, 0,
1125 senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
1126 senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
1128 /* Mark Bit(4) of oltype */
1129 const uint64x2_t oi_cksum_mask2 = {
1134 xtmp128 = vorrq_u64(xtmp128, oi_cksum_mask2);
1135 ytmp128 = vorrq_u64(ytmp128, oi_cksum_mask2);
1138 ltypes01 = vqtbl2q_u8(tbl, xtmp128);
1139 ltypes23 = vqtbl2q_u8(tbl, ytmp128);
1141 /* Pick only relevant fields i.e Bit 48:55 of iltype and
1142 * Bit 56:63 of oltype and place it in corresponding
1143 * place in senddesc_w1.
1145 const uint8x16_t shuf_mask0 = {
1146 0xFF, 0xFF, 0xFF, 0xFF, 0x7, 0x6, 0xFF, 0xFF,
1147 0xFF, 0xFF, 0xFF, 0xFF, 0xF, 0xE, 0xFF, 0xFF,
1150 ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
1151 ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
1153 /* Prepare l4ptr, l3ptr, ol4ptr, ol3ptr from
1154 * l3len, l2len, ol3len, ol2len.
1155 * a [E(32):L3(8):L2(8):OL3(8):OL2(8)]
1157 * a [E:(L3+L2):(L2+OL3):(OL3+OL2):OL2]
1159 * a [E:(L3+L2+OL3+OL2):(L2+OL3+OL2):(OL3+OL2):OL2]
1160 * => E(32):IL4PTR(8):IL3PTR(8):OL4PTR(8):OL3PTR(8)
1162 senddesc01_w1 = vaddq_u8(senddesc01_w1,
1163 vshlq_n_u32(senddesc01_w1, 8));
1164 senddesc23_w1 = vaddq_u8(senddesc23_w1,
1165 vshlq_n_u32(senddesc23_w1, 8));
1167 /* Continue preparing l4ptr, l3ptr, ol4ptr, ol3ptr */
1168 senddesc01_w1 = vaddq_u8(
1169 senddesc01_w1, vshlq_n_u32(senddesc01_w1, 16));
1170 senddesc23_w1 = vaddq_u8(
1171 senddesc23_w1, vshlq_n_u32(senddesc23_w1, 16));
1173 /* Move ltypes to senddesc*_w1 */
1174 senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
1175 senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
1178 xmask01 = vdupq_n_u64(0);
1180 asm volatile("LD1 {%[a].H}[0],[%[in]]\n\t"
1185 asm volatile("LD1 {%[a].H}[4],[%[in]]\n\t"
1190 asm volatile("LD1 {%[b].H}[0],[%[in]]\n\t"
1195 asm volatile("LD1 {%[b].H}[4],[%[in]]\n\t"
1199 xmask01 = vshlq_n_u64(xmask01, 20);
1200 xmask23 = vshlq_n_u64(xmask23, 20);
1202 senddesc01_w0 = vorrq_u64(senddesc01_w0, xmask01);
1203 senddesc23_w0 = vorrq_u64(senddesc23_w0, xmask23);
1205 if (flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
1206 /* Tx ol_flag for vlan. */
1207 const uint64x2_t olv = {PKT_TX_VLAN, PKT_TX_VLAN};
1208 /* Bit enable for VLAN1 */
1209 const uint64x2_t mlv = {BIT_ULL(49), BIT_ULL(49)};
1210 /* Tx ol_flag for QnQ. */
1211 const uint64x2_t olq = {PKT_TX_QINQ, PKT_TX_QINQ};
1212 /* Bit enable for VLAN0 */
1213 const uint64x2_t mlq = {BIT_ULL(48), BIT_ULL(48)};
1214 /* Load vlan values from packet. outer is VLAN 0 */
1215 uint64x2_t ext01 = {
1216 ((uint32_t)tx_pkts[0]->vlan_tci_outer) << 8 |
1217 ((uint64_t)tx_pkts[0]->vlan_tci) << 32,
1218 ((uint32_t)tx_pkts[1]->vlan_tci_outer) << 8 |
1219 ((uint64_t)tx_pkts[1]->vlan_tci) << 32,
1221 uint64x2_t ext23 = {
1222 ((uint32_t)tx_pkts[2]->vlan_tci_outer) << 8 |
1223 ((uint64_t)tx_pkts[2]->vlan_tci) << 32,
1224 ((uint32_t)tx_pkts[3]->vlan_tci_outer) << 8 |
1225 ((uint64_t)tx_pkts[3]->vlan_tci) << 32,
1228 /* Get ol_flags of the packets. */
1229 xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
1230 ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
1232 /* ORR vlan outer/inner values into cmd. */
1233 sendext01_w1 = vorrq_u64(sendext01_w1, ext01);
1234 sendext23_w1 = vorrq_u64(sendext23_w1, ext23);
1236 /* Test for offload enable bits and generate masks. */
1237 xtmp128 = vorrq_u64(vandq_u64(vtstq_u64(xtmp128, olv),
1239 vandq_u64(vtstq_u64(xtmp128, olq),
1241 ytmp128 = vorrq_u64(vandq_u64(vtstq_u64(ytmp128, olv),
1243 vandq_u64(vtstq_u64(ytmp128, olq),
1246 /* Set vlan enable bits into cmd based on mask. */
1247 sendext01_w1 = vorrq_u64(sendext01_w1, xtmp128);
1248 sendext23_w1 = vorrq_u64(sendext23_w1, ytmp128);
1251 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
1252 /* Tx ol_flag for timestam. */
1253 const uint64x2_t olf = {PKT_TX_IEEE1588_TMST,
1254 PKT_TX_IEEE1588_TMST};
1255 /* Set send mem alg to SUB. */
1256 const uint64x2_t alg = {BIT_ULL(59), BIT_ULL(59)};
1257 /* Increment send mem address by 8. */
1258 const uint64x2_t addr = {0x8, 0x8};
1260 xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
1261 ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
1263 /* Check if timestamp is requested and generate inverted
1264 * mask as we need not make any changes to default cmd
1267 xtmp128 = vmvnq_u32(vtstq_u64(olf, xtmp128));
1268 ytmp128 = vmvnq_u32(vtstq_u64(olf, ytmp128));
1270 /* Change send mem address to an 8 byte offset when
1271 * TSTMP is disabled.
1273 sendmem01_w1 = vaddq_u64(sendmem01_w1,
1274 vandq_u64(xtmp128, addr));
1275 sendmem23_w1 = vaddq_u64(sendmem23_w1,
1276 vandq_u64(ytmp128, addr));
1277 /* Change send mem alg to SUB when TSTMP is disabled. */
1278 sendmem01_w0 = vorrq_u64(sendmem01_w0,
1279 vandq_u64(xtmp128, alg));
1280 sendmem23_w0 = vorrq_u64(sendmem23_w0,
1281 vandq_u64(ytmp128, alg));
1283 cmd3[0] = vzip1q_u64(sendmem01_w0, sendmem01_w1);
1284 cmd3[1] = vzip2q_u64(sendmem01_w0, sendmem01_w1);
1285 cmd3[2] = vzip1q_u64(sendmem23_w0, sendmem23_w1);
1286 cmd3[3] = vzip2q_u64(sendmem23_w0, sendmem23_w1);
1289 if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
1290 /* Set don't free bit if reference count > 1 */
1291 xmask01 = vdupq_n_u64(0);
1294 /* Move mbufs to iova */
1295 mbuf0 = (uint64_t *)tx_pkts[0];
1296 mbuf1 = (uint64_t *)tx_pkts[1];
1297 mbuf2 = (uint64_t *)tx_pkts[2];
1298 mbuf3 = (uint64_t *)tx_pkts[3];
1300 if (cnxk_nix_prefree_seg((struct rte_mbuf *)mbuf0))
1301 vsetq_lane_u64(0x80000, xmask01, 0);
1303 __mempool_check_cookies(
1304 ((struct rte_mbuf *)mbuf0)->pool,
1305 (void **)&mbuf0, 1, 0);
1307 if (cnxk_nix_prefree_seg((struct rte_mbuf *)mbuf1))
1308 vsetq_lane_u64(0x80000, xmask01, 1);
1310 __mempool_check_cookies(
1311 ((struct rte_mbuf *)mbuf1)->pool,
1312 (void **)&mbuf1, 1, 0);
1314 if (cnxk_nix_prefree_seg((struct rte_mbuf *)mbuf2))
1315 vsetq_lane_u64(0x80000, xmask23, 0);
1317 __mempool_check_cookies(
1318 ((struct rte_mbuf *)mbuf2)->pool,
1319 (void **)&mbuf2, 1, 0);
1321 if (cnxk_nix_prefree_seg((struct rte_mbuf *)mbuf3))
1322 vsetq_lane_u64(0x80000, xmask23, 1);
1324 __mempool_check_cookies(
1325 ((struct rte_mbuf *)mbuf3)->pool,
1326 (void **)&mbuf3, 1, 0);
1327 senddesc01_w0 = vorrq_u64(senddesc01_w0, xmask01);
1328 senddesc23_w0 = vorrq_u64(senddesc23_w0, xmask23);
1329 /* Ensuring mbuf fields which got updated in
1330 * cnxk_nix_prefree_seg are written before LMTST.
1334 /* Move mbufs to iova */
1335 mbuf0 = (uint64_t *)tx_pkts[0];
1336 mbuf1 = (uint64_t *)tx_pkts[1];
1337 mbuf2 = (uint64_t *)tx_pkts[2];
1338 mbuf3 = (uint64_t *)tx_pkts[3];
1340 /* Mark mempool object as "put" since
1341 * it is freed by NIX
1343 __mempool_check_cookies(
1344 ((struct rte_mbuf *)mbuf0)->pool,
1345 (void **)&mbuf0, 1, 0);
1347 __mempool_check_cookies(
1348 ((struct rte_mbuf *)mbuf1)->pool,
1349 (void **)&mbuf1, 1, 0);
1351 __mempool_check_cookies(
1352 ((struct rte_mbuf *)mbuf2)->pool,
1353 (void **)&mbuf2, 1, 0);
1355 __mempool_check_cookies(
1356 ((struct rte_mbuf *)mbuf3)->pool,
1357 (void **)&mbuf3, 1, 0);
1358 #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1363 /* Create 4W cmd for 4 mbufs (sendhdr, sgdesc) */
1364 cmd0[0] = vzip1q_u64(senddesc01_w0, senddesc01_w1);
1365 cmd0[1] = vzip2q_u64(senddesc01_w0, senddesc01_w1);
1366 cmd0[2] = vzip1q_u64(senddesc23_w0, senddesc23_w1);
1367 cmd0[3] = vzip2q_u64(senddesc23_w0, senddesc23_w1);
1369 cmd1[0] = vzip1q_u64(sgdesc01_w0, sgdesc01_w1);
1370 cmd1[1] = vzip2q_u64(sgdesc01_w0, sgdesc01_w1);
1371 cmd1[2] = vzip1q_u64(sgdesc23_w0, sgdesc23_w1);
1372 cmd1[3] = vzip2q_u64(sgdesc23_w0, sgdesc23_w1);
1374 if (flags & NIX_TX_NEED_EXT_HDR) {
1375 cmd2[0] = vzip1q_u64(sendext01_w0, sendext01_w1);
1376 cmd2[1] = vzip2q_u64(sendext01_w0, sendext01_w1);
1377 cmd2[2] = vzip1q_u64(sendext23_w0, sendext23_w1);
1378 cmd2[3] = vzip2q_u64(sendext23_w0, sendext23_w1);
1381 if (flags & NIX_TX_NEED_EXT_HDR) {
1382 /* With ext header in the command we can no longer send
1383 * all 4 packets together since LMTLINE is 128bytes.
1384 * Split and Tx twice.
1387 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
1388 vst1q_u64(lmt_addr, cmd0[0]);
1389 vst1q_u64(lmt_addr + 2, cmd2[0]);
1390 vst1q_u64(lmt_addr + 4, cmd1[0]);
1391 vst1q_u64(lmt_addr + 6, cmd3[0]);
1392 vst1q_u64(lmt_addr + 8, cmd0[1]);
1393 vst1q_u64(lmt_addr + 10, cmd2[1]);
1394 vst1q_u64(lmt_addr + 12, cmd1[1]);
1395 vst1q_u64(lmt_addr + 14, cmd3[1]);
1397 vst1q_u64(lmt_addr, cmd0[0]);
1398 vst1q_u64(lmt_addr + 2, cmd2[0]);
1399 vst1q_u64(lmt_addr + 4, cmd1[0]);
1400 vst1q_u64(lmt_addr + 6, cmd0[1]);
1401 vst1q_u64(lmt_addr + 8, cmd2[1]);
1402 vst1q_u64(lmt_addr + 10, cmd1[1]);
1404 lmt_status = roc_lmt_submit_ldeor(io_addr);
1405 } while (lmt_status == 0);
1408 if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
1409 vst1q_u64(lmt_addr, cmd0[2]);
1410 vst1q_u64(lmt_addr + 2, cmd2[2]);
1411 vst1q_u64(lmt_addr + 4, cmd1[2]);
1412 vst1q_u64(lmt_addr + 6, cmd3[2]);
1413 vst1q_u64(lmt_addr + 8, cmd0[3]);
1414 vst1q_u64(lmt_addr + 10, cmd2[3]);
1415 vst1q_u64(lmt_addr + 12, cmd1[3]);
1416 vst1q_u64(lmt_addr + 14, cmd3[3]);
1418 vst1q_u64(lmt_addr, cmd0[2]);
1419 vst1q_u64(lmt_addr + 2, cmd2[2]);
1420 vst1q_u64(lmt_addr + 4, cmd1[2]);
1421 vst1q_u64(lmt_addr + 6, cmd0[3]);
1422 vst1q_u64(lmt_addr + 8, cmd2[3]);
1423 vst1q_u64(lmt_addr + 10, cmd1[3]);
1425 lmt_status = roc_lmt_submit_ldeor(io_addr);
1426 } while (lmt_status == 0);
1429 vst1q_u64(lmt_addr, cmd0[0]);
1430 vst1q_u64(lmt_addr + 2, cmd1[0]);
1431 vst1q_u64(lmt_addr + 4, cmd0[1]);
1432 vst1q_u64(lmt_addr + 6, cmd1[1]);
1433 vst1q_u64(lmt_addr + 8, cmd0[2]);
1434 vst1q_u64(lmt_addr + 10, cmd1[2]);
1435 vst1q_u64(lmt_addr + 12, cmd0[3]);
1436 vst1q_u64(lmt_addr + 14, cmd1[3]);
1437 lmt_status = roc_lmt_submit_ldeor(io_addr);
1438 } while (lmt_status == 0);
1440 tx_pkts = tx_pkts + NIX_DESCS_PER_LOOP;
1443 if (unlikely(pkts_left))
1444 pkts += cn9k_nix_xmit_pkts(tx_queue, tx_pkts, pkts_left, cmd,
1451 static __rte_always_inline uint16_t
1452 cn9k_nix_xmit_pkts_vector(void *tx_queue, struct rte_mbuf **tx_pkts,
1453 uint16_t pkts, uint64_t *cmd, const uint16_t flags)
1455 RTE_SET_USED(tx_queue);
1456 RTE_SET_USED(tx_pkts);
1459 RTE_SET_USED(flags);
1464 #define L3L4CSUM_F NIX_TX_OFFLOAD_L3_L4_CSUM_F
1465 #define OL3OL4CSUM_F NIX_TX_OFFLOAD_OL3_OL4_CSUM_F
1466 #define VLAN_F NIX_TX_OFFLOAD_VLAN_QINQ_F
1467 #define NOFF_F NIX_TX_OFFLOAD_MBUF_NOFF_F
1468 #define TSO_F NIX_TX_OFFLOAD_TSO_F
1469 #define TSP_F NIX_TX_OFFLOAD_TSTAMP_F
1471 /* [TSP] [TSO] [NOFF] [VLAN] [OL3OL4CSUM] [L3L4CSUM] */
1472 #define NIX_TX_FASTPATH_MODES \
1473 T(no_offload, 0, 0, 0, 0, 0, 0, 4, \
1474 NIX_TX_OFFLOAD_NONE) \
1475 T(l3l4csum, 0, 0, 0, 0, 0, 1, 4, \
1477 T(ol3ol4csum, 0, 0, 0, 0, 1, 0, 4, \
1479 T(ol3ol4csum_l3l4csum, 0, 0, 0, 0, 1, 1, 4, \
1480 OL3OL4CSUM_F | L3L4CSUM_F) \
1481 T(vlan, 0, 0, 0, 1, 0, 0, 6, \
1483 T(vlan_l3l4csum, 0, 0, 0, 1, 0, 1, 6, \
1484 VLAN_F | L3L4CSUM_F) \
1485 T(vlan_ol3ol4csum, 0, 0, 0, 1, 1, 0, 6, \
1486 VLAN_F | OL3OL4CSUM_F) \
1487 T(vlan_ol3ol4csum_l3l4csum, 0, 0, 0, 1, 1, 1, 6, \
1488 VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1489 T(noff, 0, 0, 1, 0, 0, 0, 4, \
1491 T(noff_l3l4csum, 0, 0, 1, 0, 0, 1, 4, \
1492 NOFF_F | L3L4CSUM_F) \
1493 T(noff_ol3ol4csum, 0, 0, 1, 0, 1, 0, 4, \
1494 NOFF_F | OL3OL4CSUM_F) \
1495 T(noff_ol3ol4csum_l3l4csum, 0, 0, 1, 0, 1, 1, 4, \
1496 NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1497 T(noff_vlan, 0, 0, 1, 1, 0, 0, 6, \
1499 T(noff_vlan_l3l4csum, 0, 0, 1, 1, 0, 1, 6, \
1500 NOFF_F | VLAN_F | L3L4CSUM_F) \
1501 T(noff_vlan_ol3ol4csum, 0, 0, 1, 1, 1, 0, 6, \
1502 NOFF_F | VLAN_F | OL3OL4CSUM_F) \
1503 T(noff_vlan_ol3ol4csum_l3l4csum, 0, 0, 1, 1, 1, 1, 6, \
1504 NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1505 T(tso, 0, 1, 0, 0, 0, 0, 6, \
1507 T(tso_l3l4csum, 0, 1, 0, 0, 0, 1, 6, \
1508 TSO_F | L3L4CSUM_F) \
1509 T(tso_ol3ol4csum, 0, 1, 0, 0, 1, 0, 6, \
1510 TSO_F | OL3OL4CSUM_F) \
1511 T(tso_ol3ol4csum_l3l4csum, 0, 1, 0, 0, 1, 1, 6, \
1512 TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1513 T(tso_vlan, 0, 1, 0, 1, 0, 0, 6, \
1515 T(tso_vlan_l3l4csum, 0, 1, 0, 1, 0, 1, 6, \
1516 TSO_F | VLAN_F | L3L4CSUM_F) \
1517 T(tso_vlan_ol3ol4csum, 0, 1, 0, 1, 1, 0, 6, \
1518 TSO_F | VLAN_F | OL3OL4CSUM_F) \
1519 T(tso_vlan_ol3ol4csum_l3l4csum, 0, 1, 0, 1, 1, 1, 6, \
1520 TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1521 T(tso_noff, 0, 1, 1, 0, 0, 0, 6, \
1523 T(tso_noff_l3l4csum, 0, 1, 1, 0, 0, 1, 6, \
1524 TSO_F | NOFF_F | L3L4CSUM_F) \
1525 T(tso_noff_ol3ol4csum, 0, 1, 1, 0, 1, 0, 6, \
1526 TSO_F | NOFF_F | OL3OL4CSUM_F) \
1527 T(tso_noff_ol3ol4csum_l3l4csum, 0, 1, 1, 0, 1, 1, 6, \
1528 TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1529 T(tso_noff_vlan, 0, 1, 1, 1, 0, 0, 6, \
1530 TSO_F | NOFF_F | VLAN_F) \
1531 T(tso_noff_vlan_l3l4csum, 0, 1, 1, 1, 0, 1, 6, \
1532 TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
1533 T(tso_noff_vlan_ol3ol4csum, 0, 1, 1, 1, 1, 0, 6, \
1534 TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
1535 T(tso_noff_vlan_ol3ol4csum_l3l4csum, 0, 1, 1, 1, 1, 1, 6, \
1536 TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1537 T(ts, 1, 0, 0, 0, 0, 0, 8, \
1539 T(ts_l3l4csum, 1, 0, 0, 0, 0, 1, 8, \
1540 TSP_F | L3L4CSUM_F) \
1541 T(ts_ol3ol4csum, 1, 0, 0, 0, 1, 0, 8, \
1542 TSP_F | OL3OL4CSUM_F) \
1543 T(ts_ol3ol4csum_l3l4csum, 1, 0, 0, 0, 1, 1, 8, \
1544 TSP_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1545 T(ts_vlan, 1, 0, 0, 1, 0, 0, 8, \
1547 T(ts_vlan_l3l4csum, 1, 0, 0, 1, 0, 1, 8, \
1548 TSP_F | VLAN_F | L3L4CSUM_F) \
1549 T(ts_vlan_ol3ol4csum, 1, 0, 0, 1, 1, 0, 8, \
1550 TSP_F | VLAN_F | OL3OL4CSUM_F) \
1551 T(ts_vlan_ol3ol4csum_l3l4csum, 1, 0, 0, 1, 1, 1, 8, \
1552 TSP_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1553 T(ts_noff, 1, 0, 1, 0, 0, 0, 8, \
1555 T(ts_noff_l3l4csum, 1, 0, 1, 0, 0, 1, 8, \
1556 TSP_F | NOFF_F | L3L4CSUM_F) \
1557 T(ts_noff_ol3ol4csum, 1, 0, 1, 0, 1, 0, 8, \
1558 TSP_F | NOFF_F | OL3OL4CSUM_F) \
1559 T(ts_noff_ol3ol4csum_l3l4csum, 1, 0, 1, 0, 1, 1, 8, \
1560 TSP_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1561 T(ts_noff_vlan, 1, 0, 1, 1, 0, 0, 8, \
1562 TSP_F | NOFF_F | VLAN_F) \
1563 T(ts_noff_vlan_l3l4csum, 1, 0, 1, 1, 0, 1, 8, \
1564 TSP_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
1565 T(ts_noff_vlan_ol3ol4csum, 1, 0, 1, 1, 1, 0, 8, \
1566 TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
1567 T(ts_noff_vlan_ol3ol4csum_l3l4csum, 1, 0, 1, 1, 1, 1, 8, \
1568 TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1569 T(ts_tso, 1, 1, 0, 0, 0, 0, 8, \
1571 T(ts_tso_l3l4csum, 1, 1, 0, 0, 0, 1, 8, \
1572 TSP_F | TSO_F | L3L4CSUM_F) \
1573 T(ts_tso_ol3ol4csum, 1, 1, 0, 0, 1, 0, 8, \
1574 TSP_F | TSO_F | OL3OL4CSUM_F) \
1575 T(ts_tso_ol3ol4csum_l3l4csum, 1, 1, 0, 0, 1, 1, 8, \
1576 TSP_F | TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1577 T(ts_tso_vlan, 1, 1, 0, 1, 0, 0, 8, \
1578 TSP_F | TSO_F | VLAN_F) \
1579 T(ts_tso_vlan_l3l4csum, 1, 1, 0, 1, 0, 1, 8, \
1580 TSP_F | TSO_F | VLAN_F | L3L4CSUM_F) \
1581 T(ts_tso_vlan_ol3ol4csum, 1, 1, 0, 1, 1, 0, 8, \
1582 TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F) \
1583 T(ts_tso_vlan_ol3ol4csum_l3l4csum, 1, 1, 0, 1, 1, 1, 8, \
1584 TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1585 T(ts_tso_noff, 1, 1, 1, 0, 0, 0, 8, \
1586 TSP_F | TSO_F | NOFF_F) \
1587 T(ts_tso_noff_l3l4csum, 1, 1, 1, 0, 0, 1, 8, \
1588 TSP_F | TSO_F | NOFF_F | L3L4CSUM_F) \
1589 T(ts_tso_noff_ol3ol4csum, 1, 1, 1, 0, 1, 0, 8, \
1590 TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F) \
1591 T(ts_tso_noff_ol3ol4csum_l3l4csum, 1, 1, 1, 0, 1, 1, 8, \
1592 TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
1593 T(ts_tso_noff_vlan, 1, 1, 1, 1, 0, 0, 8, \
1594 TSP_F | TSO_F | NOFF_F | VLAN_F) \
1595 T(ts_tso_noff_vlan_l3l4csum, 1, 1, 1, 1, 0, 1, 8, \
1596 TSP_F | TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
1597 T(ts_tso_noff_vlan_ol3ol4csum, 1, 1, 1, 1, 1, 0, 8, \
1598 TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
1599 T(ts_tso_noff_vlan_ol3ol4csum_l3l4csum, 1, 1, 1, 1, 1, 1, 8, \
1600 TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
1602 #define T(name, f5, f4, f3, f2, f1, f0, sz, flags) \
1603 uint16_t __rte_noinline __rte_hot cn9k_nix_xmit_pkts_##name( \
1604 void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts); \
1606 uint16_t __rte_noinline __rte_hot cn9k_nix_xmit_pkts_mseg_##name( \
1607 void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts); \
1609 uint16_t __rte_noinline __rte_hot cn9k_nix_xmit_pkts_vec_##name( \
1610 void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts);
1612 NIX_TX_FASTPATH_MODES
1615 #endif /* __CN9K_TX_H__ */