Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : : #ifndef __CN20K_TX_H__
5 : : #define __CN20K_TX_H__
6 : :
7 : : #include "cn20k_rxtx.h"
8 : : #include <rte_eventdev.h>
9 : : #include <rte_vect.h>
10 : :
11 : : #define NIX_TX_OFFLOAD_NONE (0)
12 : : #define NIX_TX_OFFLOAD_L3_L4_CSUM_F BIT(0)
13 : : #define NIX_TX_OFFLOAD_OL3_OL4_CSUM_F BIT(1)
14 : : #define NIX_TX_OFFLOAD_VLAN_QINQ_F BIT(2)
15 : : #define NIX_TX_OFFLOAD_MBUF_NOFF_F BIT(3)
16 : : #define NIX_TX_OFFLOAD_TSO_F BIT(4)
17 : : #define NIX_TX_OFFLOAD_TSTAMP_F BIT(5)
18 : : #define NIX_TX_OFFLOAD_SECURITY_F BIT(6)
19 : : #define NIX_TX_OFFLOAD_MAX (NIX_TX_OFFLOAD_SECURITY_F << 1)
20 : :
21 : : /* Flags to control xmit_prepare function.
22 : : * Defining it from backwards to denote its been
23 : : * not used as offload flags to pick function
24 : : */
25 : : #define NIX_TX_VWQE_F BIT(14)
26 : : #define NIX_TX_MULTI_SEG_F BIT(15)
27 : :
28 : : #define NIX_TX_NEED_SEND_HDR_W1 \
29 : : (NIX_TX_OFFLOAD_L3_L4_CSUM_F | NIX_TX_OFFLOAD_OL3_OL4_CSUM_F | \
30 : : NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSO_F)
31 : :
32 : : #define NIX_TX_NEED_EXT_HDR \
33 : : (NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSTAMP_F | NIX_TX_OFFLOAD_TSO_F)
34 : :
35 : : #define NIX_XMIT_FC_OR_RETURN(txq, pkts) \
36 : : do { \
37 : : int64_t avail; \
38 : : /* Cached value is low, Update the fc_cache_pkts */ \
39 : : if (unlikely((txq)->fc_cache_pkts < (pkts))) { \
40 : : avail = txq->nb_sqb_bufs_adj - *txq->fc_mem; \
41 : : /* Multiply with sqe_per_sqb to express in pkts */ \
42 : : (txq)->fc_cache_pkts = (avail << (txq)->sqes_per_sqb_log2) - avail; \
43 : : /* Check it again for the room */ \
44 : : if (unlikely((txq)->fc_cache_pkts < (pkts))) \
45 : : return 0; \
46 : : } \
47 : : } while (0)
48 : :
49 : : #define NIX_XMIT_FC_OR_RETURN_MTS(txq, pkts) \
50 : : do { \
51 : : int64_t __rte_atomic *fc_cache = &(txq)->fc_cache_pkts; \
52 : : uint8_t retry_count = 8; \
53 : : int64_t val, newval; \
54 : : retry: \
55 : : /* Reduce the cached count */ \
56 : : val = (int64_t)rte_atomic_fetch_sub_explicit(fc_cache, pkts, \
57 : : rte_memory_order_relaxed); \
58 : : val -= pkts; \
59 : : /* Cached value is low, Update the fc_cache_pkts */ \
60 : : if (unlikely(val < 0)) { \
61 : : /* Multiply with sqe_per_sqb to express in pkts */ \
62 : : newval = txq->nb_sqb_bufs_adj - \
63 : : rte_atomic_load_explicit(txq->fc_mem, rte_memory_order_relaxed); \
64 : : newval = (newval << (txq)->sqes_per_sqb_log2) - newval; \
65 : : newval -= pkts; \
66 : : if (!rte_atomic_compare_exchange_strong_explicit( \
67 : : fc_cache, &val, newval, rte_memory_order_relaxed, \
68 : : rte_memory_order_relaxed)) { \
69 : : if (retry_count) { \
70 : : retry_count--; \
71 : : goto retry; \
72 : : } else \
73 : : return 0; \
74 : : } \
75 : : /* Update and check it again for the room */ \
76 : : if (unlikely(newval < 0)) \
77 : : return 0; \
78 : : } \
79 : : } while (0)
80 : :
81 : : #define NIX_XMIT_FC_CHECK_RETURN(txq, pkts) \
82 : : do { \
83 : : if (unlikely((txq)->flag)) \
84 : : NIX_XMIT_FC_OR_RETURN_MTS(txq, pkts); \
85 : : else { \
86 : : NIX_XMIT_FC_OR_RETURN(txq, pkts); \
87 : : /* Reduce the cached count */ \
88 : : txq->fc_cache_pkts -= pkts; \
89 : : } \
90 : : } while (0)
91 : :
92 : : /* Encoded number of segments to number of dwords macro, each value of nb_segs
93 : : * is encoded as 4bits.
94 : : */
95 : : #define NIX_SEGDW_MAGIC 0x76654432210ULL
96 : :
97 : : #define NIX_NB_SEGS_TO_SEGDW(x) ((NIX_SEGDW_MAGIC >> ((x) << 2)) & 0xF)
98 : :
99 : : static __plt_always_inline uint8_t
100 : : cn20k_nix_mbuf_sg_dwords(struct rte_mbuf *m)
101 : : {
102 : : uint32_t nb_segs = m->nb_segs;
103 : : uint16_t aura0, aura;
104 : : int segw, sg_segs;
105 : :
106 : : aura0 = roc_npa_aura_handle_to_aura(m->pool->pool_id);
107 : :
108 : : nb_segs--;
109 : : segw = 2;
110 : : sg_segs = 1;
111 : : while (nb_segs) {
112 : : m = m->next;
113 : : aura = roc_npa_aura_handle_to_aura(m->pool->pool_id);
114 : : if (aura != aura0) {
115 : : segw += 2 + (sg_segs == 2);
116 : : sg_segs = 0;
117 : : } else {
118 : : segw += (sg_segs == 0); /* SUBDC */
119 : : segw += 1; /* IOVA */
120 : : sg_segs += 1;
121 : : sg_segs %= 3;
122 : : }
123 : : nb_segs--;
124 : : }
125 : :
126 : : return (segw + 1) / 2;
127 : : }
128 : :
129 : : static __plt_always_inline void
130 : : cn20k_nix_tx_mbuf_validate(struct rte_mbuf *m, const uint32_t flags)
131 : : {
132 : : #ifdef RTE_LIBRTE_MBUF_DEBUG
133 : : uint16_t segdw;
134 : :
135 : : segdw = cn20k_nix_mbuf_sg_dwords(m);
136 : : segdw += 1 + !!(flags & NIX_TX_NEED_EXT_HDR) + !!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
137 : :
138 : : PLT_ASSERT(segdw <= 8);
139 : : #else
140 : : RTE_SET_USED(m);
141 : : RTE_SET_USED(flags);
142 : : #endif
143 : : }
144 : :
145 : : static __plt_always_inline void
146 : : cn20k_nix_vwqe_wait_fc(struct cn20k_eth_txq *txq, uint16_t req)
147 : : {
148 : : int64_t cached, refill;
149 : : int64_t pkts;
150 : :
151 : : retry:
152 : : #ifdef RTE_ARCH_ARM64
153 : :
154 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
155 : : " ldxr %[pkts], [%[addr]] \n"
156 : : " tbz %[pkts], 63, .Ldne%= \n"
157 : : " sevl \n"
158 : : ".Lrty%=: wfe \n"
159 : : " ldxr %[pkts], [%[addr]] \n"
160 : : " tbnz %[pkts], 63, .Lrty%= \n"
161 : : ".Ldne%=: \n"
162 : : : [pkts] "=&r"(pkts)
163 : : : [addr] "r"(&txq->fc_cache_pkts)
164 : : : "memory");
165 : : #else
166 : : RTE_SET_USED(pkts);
167 : : while (rte_atomic_load_explicit(&txq->fc_cache_pkts, rte_memory_order_relaxed) < 0)
168 : : ;
169 : : #endif
170 : : cached = rte_atomic_fetch_sub_explicit(&txq->fc_cache_pkts, req, rte_memory_order_acquire) -
171 : : req;
172 : : /* Check if there is enough space, else update and retry. */
173 : : if (cached >= 0)
174 : : return;
175 : :
176 : : /* Check if we have space else retry. */
177 : : #ifdef RTE_ARCH_ARM64
178 : : int64_t val;
179 : :
180 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
181 : : " ldxr %[val], [%[addr]] \n"
182 : : " sub %[val], %[adj], %[val] \n"
183 : : " lsl %[refill], %[val], %[shft] \n"
184 : : " sub %[refill], %[refill], %[val] \n"
185 : : " sub %[refill], %[refill], %[sub] \n"
186 : : " cmp %[refill], #0x0 \n"
187 : : " b.ge .Ldne%= \n"
188 : : " sevl \n"
189 : : ".Lrty%=: wfe \n"
190 : : " ldxr %[val], [%[addr]] \n"
191 : : " sub %[val], %[adj], %[val] \n"
192 : : " lsl %[refill], %[val], %[shft] \n"
193 : : " sub %[refill], %[refill], %[val] \n"
194 : : " sub %[refill], %[refill], %[sub] \n"
195 : : " cmp %[refill], #0x0 \n"
196 : : " b.lt .Lrty%= \n"
197 : : ".Ldne%=: \n"
198 : : : [refill] "=&r"(refill), [val] "=&r" (val)
199 : : : [addr] "r"(txq->fc_mem), [adj] "r"(txq->nb_sqb_bufs_adj),
200 : : [shft] "r"(txq->sqes_per_sqb_log2), [sub] "r"(req)
201 : : : "memory");
202 : : #else
203 : : do {
204 : : refill = (txq->nb_sqb_bufs_adj -
205 : : rte_atomic_load_explicit(txq->fc_mem, rte_memory_order_relaxed));
206 : : refill = (refill << txq->sqes_per_sqb_log2) - refill;
207 : : refill -= req;
208 : : } while (refill < 0);
209 : : #endif
210 : : if (!rte_atomic_compare_exchange_strong_explicit(&txq->fc_cache_pkts, &cached, refill,
211 : : rte_memory_order_release,
212 : : rte_memory_order_relaxed))
213 : : goto retry;
214 : : }
215 : :
216 : : /* Function to determine no of tx subdesc required in case ext
217 : : * sub desc is enabled.
218 : : */
219 : : static __rte_always_inline int
220 : : cn20k_nix_tx_ext_subs(const uint16_t flags)
221 : : {
222 : : return (flags & NIX_TX_OFFLOAD_TSTAMP_F) ?
223 : : 2 :
224 : : ((flags & (NIX_TX_OFFLOAD_VLAN_QINQ_F | NIX_TX_OFFLOAD_TSO_F)) ? 1 : 0);
225 : : }
226 : :
227 : : static __rte_always_inline uint8_t
228 : : cn20k_nix_tx_dwords(const uint16_t flags, const uint8_t segdw)
229 : : {
230 : : if (!(flags & NIX_TX_MULTI_SEG_F))
231 : : return cn20k_nix_tx_ext_subs(flags) + 2;
232 : :
233 : : /* Already everything is accounted for in segdw */
234 : : return segdw;
235 : : }
236 : :
237 : : static __rte_always_inline uint8_t
238 : : cn20k_nix_pkts_per_vec_brst(const uint16_t flags)
239 : : {
240 : : return ((flags & NIX_TX_NEED_EXT_HDR) ? 2 : 4) << ROC_LMT_LINES_PER_CORE_LOG2;
241 : : }
242 : :
243 : : static __rte_always_inline uint8_t
244 : : cn20k_nix_tx_dwords_per_line(const uint16_t flags)
245 : : {
246 : : return (flags & NIX_TX_NEED_EXT_HDR) ? ((flags & NIX_TX_OFFLOAD_TSTAMP_F) ? 8 : 6) : 8;
247 : : }
248 : :
249 : : static __rte_always_inline uint64_t
250 : : cn20k_nix_tx_steor_data(const uint16_t flags)
251 : : {
252 : : const uint64_t dw_m1 = cn20k_nix_tx_ext_subs(flags) + 1;
253 : : uint64_t data;
254 : :
255 : : /* This will be moved to addr area */
256 : : data = dw_m1;
257 : : /* 15 vector sizes for single seg */
258 : : data |= dw_m1 << 19;
259 : : data |= dw_m1 << 22;
260 : : data |= dw_m1 << 25;
261 : : data |= dw_m1 << 28;
262 : : data |= dw_m1 << 31;
263 : : data |= dw_m1 << 34;
264 : : data |= dw_m1 << 37;
265 : : data |= dw_m1 << 40;
266 : : data |= dw_m1 << 43;
267 : : data |= dw_m1 << 46;
268 : : data |= dw_m1 << 49;
269 : : data |= dw_m1 << 52;
270 : : data |= dw_m1 << 55;
271 : : data |= dw_m1 << 58;
272 : : data |= dw_m1 << 61;
273 : :
274 : : return data;
275 : : }
276 : :
277 : : static __rte_always_inline uint8_t
278 : : cn20k_nix_tx_dwords_per_line_seg(const uint16_t flags)
279 : : {
280 : : return ((flags & NIX_TX_NEED_EXT_HDR) ? (flags & NIX_TX_OFFLOAD_TSTAMP_F) ? 8 : 6 : 4);
281 : : }
282 : :
283 : : static __rte_always_inline uint64_t
284 : : cn20k_nix_tx_steor_vec_data(const uint16_t flags)
285 : : {
286 : : const uint64_t dw_m1 = cn20k_nix_tx_dwords_per_line(flags) - 1;
287 : : uint64_t data;
288 : :
289 : : /* This will be moved to addr area */
290 : : data = dw_m1;
291 : : /* 15 vector sizes for single seg */
292 : : data |= dw_m1 << 19;
293 : : data |= dw_m1 << 22;
294 : : data |= dw_m1 << 25;
295 : : data |= dw_m1 << 28;
296 : : data |= dw_m1 << 31;
297 : : data |= dw_m1 << 34;
298 : : data |= dw_m1 << 37;
299 : : data |= dw_m1 << 40;
300 : : data |= dw_m1 << 43;
301 : : data |= dw_m1 << 46;
302 : : data |= dw_m1 << 49;
303 : : data |= dw_m1 << 52;
304 : : data |= dw_m1 << 55;
305 : : data |= dw_m1 << 58;
306 : : data |= dw_m1 << 61;
307 : :
308 : : return data;
309 : : }
310 : :
311 : : static __rte_always_inline void
312 : : cn20k_nix_tx_skeleton(struct cn20k_eth_txq *txq, uint64_t *cmd, const uint16_t flags,
313 : : const uint16_t static_sz)
314 : : {
315 : : if (static_sz)
316 : 0 : cmd[0] = txq->send_hdr_w0;
317 : : else
318 : 0 : cmd[0] = (txq->send_hdr_w0 & 0xFFFFF00000000000) |
319 : : ((uint64_t)(cn20k_nix_tx_ext_subs(flags) + 1) << 40);
320 : : cmd[1] = 0;
321 : :
322 : : if (flags & NIX_TX_NEED_EXT_HDR) {
323 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F)
324 : 0 : cmd[2] = (NIX_SUBDC_EXT << 60) | BIT_ULL(15);
325 : : else
326 : : cmd[2] = NIX_SUBDC_EXT << 60;
327 : 0 : cmd[3] = 0;
328 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
329 : : cmd[4] = (NIX_SUBDC_SG << 60) | (NIX_SENDLDTYPE_LDWB << 58) | BIT_ULL(48);
330 : : else
331 : 0 : cmd[4] = (NIX_SUBDC_SG << 60) | BIT_ULL(48);
332 : : } else {
333 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
334 : : cmd[2] = (NIX_SUBDC_SG << 60) | (NIX_SENDLDTYPE_LDWB << 58) | BIT_ULL(48);
335 : : else
336 : 0 : cmd[2] = (NIX_SUBDC_SG << 60) | BIT_ULL(48);
337 : : }
338 : : }
339 : :
340 : : static __rte_always_inline void
341 : : cn20k_nix_sec_fc_wait_one(struct cn20k_eth_txq *txq)
342 : : {
343 : 0 : uint64_t nb_desc = txq->cpt_desc;
344 : : uint64_t fc;
345 : :
346 : : #ifdef RTE_ARCH_ARM64
347 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
348 : : " ldxr %[space], [%[addr]] \n"
349 : : " cmp %[nb_desc], %[space] \n"
350 : : " b.hi .Ldne%= \n"
351 : : " sevl \n"
352 : : ".Lrty%=: wfe \n"
353 : : " ldxr %[space], [%[addr]] \n"
354 : : " cmp %[nb_desc], %[space] \n"
355 : : " b.ls .Lrty%= \n"
356 : : ".Ldne%=: \n"
357 : : : [space] "=&r"(fc)
358 : : : [nb_desc] "r"(nb_desc), [addr] "r"(txq->cpt_fc)
359 : : : "memory");
360 : : #else
361 : : RTE_SET_USED(fc);
362 [ # # # # ]: 0 : while (nb_desc <= rte_atomic_load_explicit(txq->cpt_fc, rte_memory_order_relaxed))
363 : : ;
364 : : #endif
365 : : }
366 : :
367 : : static __rte_always_inline void
368 : : cn20k_nix_sec_fc_wait(struct cn20k_eth_txq *txq, uint16_t nb_pkts)
369 : : {
370 : : int32_t nb_desc, val, newval;
371 : : int32_t __rte_atomic *fc_sw;
372 : : uint64_t __rte_atomic *fc;
373 : :
374 : : /* Check if there is any CPT instruction to submit */
375 : : if (!nb_pkts)
376 : : return;
377 : :
378 : : again:
379 : : fc_sw = txq->cpt_fc_sw;
380 : : #ifdef RTE_ARCH_ARM64
381 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
382 : : " ldxr %w[pkts], [%[addr]] \n"
383 : : " tbz %w[pkts], 31, .Ldne%= \n"
384 : : " sevl \n"
385 : : ".Lrty%=: wfe \n"
386 : : " ldxr %w[pkts], [%[addr]] \n"
387 : : " tbnz %w[pkts], 31, .Lrty%= \n"
388 : : ".Ldne%=: \n"
389 : : : [pkts] "=&r"(val)
390 : : : [addr] "r"(fc_sw)
391 : : : "memory");
392 : : #else
393 : : /* Wait for primary core to refill FC. */
394 : : while (rte_atomic_load_explicit(fc_sw, rte_memory_order_relaxed) < 0)
395 : : ;
396 : : #endif
397 : :
398 : : val = rte_atomic_fetch_sub_explicit(fc_sw, nb_pkts, rte_memory_order_acquire) - nb_pkts;
399 : : if (likely(val >= 0))
400 : : return;
401 : :
402 : : nb_desc = txq->cpt_desc;
403 : : fc = txq->cpt_fc;
404 : : #ifdef RTE_ARCH_ARM64
405 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
406 : : " ldxr %[refill], [%[addr]] \n"
407 : : " sub %[refill], %[desc], %[refill] \n"
408 : : " sub %[refill], %[refill], %[pkts] \n"
409 : : " cmp %[refill], #0x0 \n"
410 : : " b.ge .Ldne%= \n"
411 : : " sevl \n"
412 : : ".Lrty%=: wfe \n"
413 : : " ldxr %[refill], [%[addr]] \n"
414 : : " sub %[refill], %[desc], %[refill] \n"
415 : : " sub %[refill], %[refill], %[pkts] \n"
416 : : " cmp %[refill], #0x0 \n"
417 : : " b.lt .Lrty%= \n"
418 : : ".Ldne%=: \n"
419 : : : [refill] "=&r"(newval)
420 : : : [addr] "r"(fc), [desc] "r"(nb_desc), [pkts] "r"(nb_pkts)
421 : : : "memory");
422 : : #else
423 : : while (true) {
424 : : newval = nb_desc - rte_atomic_load_explicit(fc, rte_memory_order_relaxed);
425 : : newval -= nb_pkts;
426 : : if (newval >= 0)
427 : : break;
428 : : }
429 : : #endif
430 : :
431 : : if (!rte_atomic_compare_exchange_strong_explicit(fc_sw, &val, newval,
432 : : rte_memory_order_release,
433 : : rte_memory_order_relaxed))
434 : : goto again;
435 : : }
436 : :
437 : : #if defined(RTE_ARCH_ARM64)
438 : : static __rte_always_inline void
439 : : cn20k_nix_prep_sec_vec(struct rte_mbuf *m, uint64x2_t *cmd0, uint64x2_t *cmd1,
440 : : uintptr_t *nixtx_addr, uintptr_t lbase, uint8_t *lnum, uint8_t *loff,
441 : : uint8_t *shft, uint64_t sa_base, const uint16_t flags)
442 : : {
443 : : struct cn20k_sec_sess_priv sess_priv;
444 : : uint32_t pkt_len, dlen_adj, rlen;
445 : : uint8_t l3l4type, chksum;
446 : : uint64x2_t cmd01, cmd23;
447 : : uint64_t sa, cpt_cq_ena;
448 : : uint8_t l2_len, l3_len;
449 : : uintptr_t dptr, nixtx;
450 : : uint64_t ucode_cmd[4];
451 : : uint64_t *laddr, w0;
452 : : uint16_t tag;
453 : :
454 : : sess_priv.u64 = *rte_security_dynfield(m);
455 : : cpt_cq_ena = sess_priv.cpt_cq_ena;
456 : :
457 : : if (flags & NIX_TX_NEED_SEND_HDR_W1) {
458 : : /* Extract l3l4type either from il3il4type or ol3ol4type */
459 : : if (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F && flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) {
460 : : l2_len = vgetq_lane_u8(*cmd0, 10);
461 : : /* L4 ptr from send hdr includes l2 and l3 len */
462 : : l3_len = vgetq_lane_u8(*cmd0, 11) - l2_len;
463 : : l3l4type = vgetq_lane_u8(*cmd0, 13);
464 : : } else {
465 : : l2_len = vgetq_lane_u8(*cmd0, 8);
466 : : /* L4 ptr from send hdr includes l2 and l3 len */
467 : : l3_len = vgetq_lane_u8(*cmd0, 9) - l2_len;
468 : : l3l4type = vgetq_lane_u8(*cmd0, 12);
469 : : }
470 : :
471 : : chksum = (l3l4type & 0x1) << 1 | !!(l3l4type & 0x30);
472 : : chksum = ~chksum;
473 : : sess_priv.chksum = sess_priv.chksum & chksum;
474 : : /* Clear SEND header flags */
475 : : *cmd0 = vsetq_lane_u16(0, *cmd0, 6);
476 : : } else {
477 : : l2_len = m->l2_len;
478 : : l3_len = m->l3_len;
479 : : }
480 : :
481 : : /* Retrieve DPTR */
482 : : dptr = vgetq_lane_u64(*cmd1, 1);
483 : : pkt_len = vgetq_lane_u16(*cmd0, 0);
484 : :
485 : : /* Calculate dlen adj */
486 : : dlen_adj = pkt_len - l2_len;
487 : : /* Exclude l3 len from roundup for transport mode */
488 : : dlen_adj -= sess_priv.mode ? 0 : l3_len;
489 : : rlen = (dlen_adj + sess_priv.roundup_len) + (sess_priv.roundup_byte - 1);
490 : : rlen &= ~(uint64_t)(sess_priv.roundup_byte - 1);
491 : : rlen += sess_priv.partial_len;
492 : : dlen_adj = rlen - dlen_adj;
493 : :
494 : : /* Update send descriptors. Security is single segment only */
495 : : *cmd0 = vsetq_lane_u16(pkt_len + dlen_adj, *cmd0, 0);
496 : :
497 : : /* CPT word 5 and word 6 */
498 : : w0 = 0;
499 : : ucode_cmd[2] = 0;
500 : : if (flags & NIX_TX_MULTI_SEG_F && m->nb_segs > 1) {
501 : : struct rte_mbuf *last = rte_pktmbuf_lastseg(m);
502 : :
503 : : /* Get area where NIX descriptor needs to be stored */
504 : : nixtx = rte_pktmbuf_mtod_offset(last, uintptr_t, last->data_len + dlen_adj);
505 : : nixtx += BIT_ULL(7);
506 : : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
507 : : nixtx += 16;
508 : :
509 : : dptr = nixtx + ((flags & NIX_TX_NEED_EXT_HDR) ? 32 : 16);
510 : :
511 : : /* Set l2 length as data offset */
512 : : w0 = (uint64_t)l2_len << 16;
513 : : w0 |= cn20k_nix_tx_ext_subs(flags) + NIX_NB_SEGS_TO_SEGDW(m->nb_segs);
514 : : ucode_cmd[1] = dptr | ((uint64_t)m->nb_segs << 60);
515 : : } else {
516 : : /* Get area where NIX descriptor needs to be stored */
517 : : nixtx = dptr + pkt_len + dlen_adj;
518 : : nixtx += BIT_ULL(7);
519 : : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
520 : : nixtx += 16;
521 : :
522 : : w0 |= cn20k_nix_tx_ext_subs(flags) + 1ULL;
523 : : w0 |= sess_priv.chksum ? BIT_ULL(63) : BIT_ULL(62);
524 : : dptr += l2_len;
525 : : ucode_cmd[1] = dptr;
526 : : *cmd1 = vsetq_lane_u16(pkt_len + dlen_adj, *cmd1, 0);
527 : : /* DLEN passed is excluding L2 HDR */
528 : : pkt_len -= l2_len;
529 : : }
530 : : w0 |= ((((int64_t)nixtx - (int64_t)dptr) & 0xFFFFF) << 32);
531 : : /* CPT word 0 and 1 */
532 : : cmd01 = vdupq_n_u64(0);
533 : : cmd01 = vsetq_lane_u64(w0, cmd01, 0);
534 : : /* CPT_RES_S is 16B above NIXTX */
535 : : cmd01 = vsetq_lane_u64((nixtx - 16) | cpt_cq_ena << 63, cmd01, 1);
536 : :
537 : : /* Return nixtx addr */
538 : : *nixtx_addr = nixtx;
539 : :
540 : : /* CPT Word 4 and Word 7 */
541 : : tag = sa_base & 0xFFFFUL;
542 : : sa_base &= ~0xFFFFUL;
543 : : sa = (uintptr_t)roc_nix_inl_ot_ipsec_outb_sa(sa_base, sess_priv.sa_idx);
544 : : ucode_cmd[3] = (ROC_CPT_DFLT_ENG_GRP_SE << 61 | 1UL << 60 | sa);
545 : : ucode_cmd[0] = (ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC << 48 | 1UL << 54 |
546 : : ((uint64_t)sess_priv.chksum) << 32 | ((uint64_t)sess_priv.dec_ttl) << 34 |
547 : : pkt_len);
548 : :
549 : : /* CPT word 2 and 3 */
550 : : cmd23 = vdupq_n_u64(0);
551 : : cmd23 = vsetq_lane_u64((((uint64_t)RTE_EVENT_TYPE_CPU << 28) | tag |
552 : : CNXK_ETHDEV_SEC_OUTB_EV_SUB << 20), cmd23, 0);
553 : : cmd23 = vsetq_lane_u64((uintptr_t)m | 1, cmd23, 1);
554 : :
555 : : /* Move to our line */
556 : : laddr = LMT_OFF(lbase, *lnum, *loff ? 64 : 0);
557 : :
558 : : /* Write CPT instruction to lmt line */
559 : : vst1q_u64(laddr, cmd01);
560 : : vst1q_u64((laddr + 2), cmd23);
561 : :
562 : : *(__uint128_t *)(laddr + 4) = *(__uint128_t *)ucode_cmd;
563 : : *(__uint128_t *)(laddr + 6) = *(__uint128_t *)(ucode_cmd + 2);
564 : :
565 : : /* Move to next line for every other CPT inst */
566 : : *loff = !(*loff);
567 : : *lnum = *lnum + (*loff ? 0 : 1);
568 : : *shft = *shft + (*loff ? 0 : 3);
569 : : }
570 : :
571 : : static __rte_always_inline void
572 : : cn20k_nix_prep_sec(struct rte_mbuf *m, uint64_t *cmd, uintptr_t *nixtx_addr, uintptr_t lbase,
573 : : uint8_t *lnum, uint8_t *loff, uint8_t *shft, uint64_t sa_base,
574 : : const uint16_t flags)
575 : : {
576 : : struct cn20k_sec_sess_priv sess_priv;
577 : : uint32_t pkt_len, dlen_adj, rlen;
578 : : struct nix_send_hdr_s *send_hdr;
579 : : uint8_t l3l4type, chksum;
580 : : uint64x2_t cmd01, cmd23;
581 : : union nix_send_sg_s *sg;
582 : : uint64_t sa, cpt_cq_ena;
583 : : uint8_t l2_len, l3_len;
584 : : uintptr_t dptr, nixtx;
585 : : uint64_t ucode_cmd[4];
586 : : uint64_t *laddr, w0;
587 : : uint16_t tag;
588 : :
589 : : /* Move to our line from base */
590 : : sess_priv.u64 = *rte_security_dynfield(m);
591 : : cpt_cq_ena = sess_priv.cpt_cq_ena;
592 : : send_hdr = (struct nix_send_hdr_s *)cmd;
593 : : if (flags & NIX_TX_NEED_EXT_HDR)
594 : : sg = (union nix_send_sg_s *)&cmd[4];
595 : : else
596 : : sg = (union nix_send_sg_s *)&cmd[2];
597 : :
598 : : if (flags & NIX_TX_NEED_SEND_HDR_W1) {
599 : : /* Extract l3l4type either from il3il4type or ol3ol4type */
600 : : if (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F && flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) {
601 : : l2_len = (cmd[1] >> 16) & 0xFF;
602 : : /* L4 ptr from send hdr includes l2 and l3 len */
603 : : l3_len = ((cmd[1] >> 24) & 0xFF) - l2_len;
604 : : l3l4type = (cmd[1] >> 40) & 0xFF;
605 : : } else {
606 : : l2_len = cmd[1] & 0xFF;
607 : : /* L4 ptr from send hdr includes l2 and l3 len */
608 : : l3_len = ((cmd[1] >> 8) & 0xFF) - l2_len;
609 : : l3l4type = (cmd[1] >> 32) & 0xFF;
610 : : }
611 : :
612 : : chksum = (l3l4type & 0x1) << 1 | !!(l3l4type & 0x30);
613 : : chksum = ~chksum;
614 : : sess_priv.chksum = sess_priv.chksum & chksum;
615 : : /* Clear SEND header flags */
616 : : cmd[1] &= ~(0xFFFFUL << 32);
617 : : } else {
618 : : l2_len = m->l2_len;
619 : : l3_len = m->l3_len;
620 : : }
621 : :
622 : : /* Retrieve DPTR */
623 : : dptr = *(uint64_t *)(sg + 1);
624 : : pkt_len = send_hdr->w0.total;
625 : :
626 : : /* Calculate dlen adj */
627 : : dlen_adj = pkt_len - l2_len;
628 : : /* Exclude l3 len from roundup for transport mode */
629 : : dlen_adj -= sess_priv.mode ? 0 : l3_len;
630 : : rlen = (dlen_adj + sess_priv.roundup_len) + (sess_priv.roundup_byte - 1);
631 : : rlen &= ~(uint64_t)(sess_priv.roundup_byte - 1);
632 : : rlen += sess_priv.partial_len;
633 : : dlen_adj = rlen - dlen_adj;
634 : :
635 : : /* Update send descriptors. Security is single segment only */
636 : : send_hdr->w0.total = pkt_len + dlen_adj;
637 : :
638 : : /* CPT word 5 and word 6 */
639 : : w0 = 0;
640 : : ucode_cmd[2] = 0;
641 : : if (flags & NIX_TX_MULTI_SEG_F && m->nb_segs > 1) {
642 : : struct rte_mbuf *last = rte_pktmbuf_lastseg(m);
643 : :
644 : : /* Get area where NIX descriptor needs to be stored */
645 : : nixtx = rte_pktmbuf_mtod_offset(last, uintptr_t, last->data_len + dlen_adj);
646 : : nixtx += BIT_ULL(7);
647 : : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
648 : : nixtx += 16;
649 : :
650 : : dptr = nixtx + ((flags & NIX_TX_NEED_EXT_HDR) ? 32 : 16);
651 : :
652 : : /* Set l2 length as data offset */
653 : : w0 = (uint64_t)l2_len << 16;
654 : : w0 |= cn20k_nix_tx_ext_subs(flags) + NIX_NB_SEGS_TO_SEGDW(m->nb_segs);
655 : : ucode_cmd[1] = dptr | ((uint64_t)m->nb_segs << 60);
656 : : } else {
657 : : /* Get area where NIX descriptor needs to be stored */
658 : : nixtx = dptr + pkt_len + dlen_adj;
659 : : nixtx += BIT_ULL(7);
660 : : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
661 : : nixtx += 16;
662 : :
663 : : w0 |= cn20k_nix_tx_ext_subs(flags) + 1ULL;
664 : : w0 |= sess_priv.chksum ? BIT_ULL(63) : BIT_ULL(62);
665 : : dptr += l2_len;
666 : : ucode_cmd[1] = dptr;
667 : : sg->seg1_size = pkt_len + dlen_adj;
668 : : pkt_len -= l2_len;
669 : : }
670 : : w0 |= ((((int64_t)nixtx - (int64_t)dptr) & 0xFFFFF) << 32);
671 : : /* CPT word 0 and 1 */
672 : : cmd01 = vdupq_n_u64(0);
673 : : cmd01 = vsetq_lane_u64(w0, cmd01, 0);
674 : : /* CPT_RES_S is 16B above NIXTX */
675 : : /* CQ_ENA for cpt */
676 : : cmd01 = vsetq_lane_u64((nixtx - 16) | cpt_cq_ena << 63, cmd01, 1);
677 : :
678 : : /* Return nixtx addr */
679 : : *nixtx_addr = nixtx;
680 : :
681 : : /* CPT Word 4 and Word 7 */
682 : : tag = sa_base & 0xFFFFUL;
683 : : sa_base &= ~0xFFFFUL;
684 : : sa = (uintptr_t)roc_nix_inl_ot_ipsec_outb_sa(sa_base, sess_priv.sa_idx);
685 : : ucode_cmd[3] = (ROC_CPT_DFLT_ENG_GRP_SE << 61 | 1UL << 60 | sa);
686 : : ucode_cmd[0] = (ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC << 48 | 1UL << 54 |
687 : : ((uint64_t)sess_priv.chksum) << 32 | ((uint64_t)sess_priv.dec_ttl) << 34 |
688 : : pkt_len);
689 : :
690 : : /* CPT word 2 and 3 */
691 : : cmd23 = vdupq_n_u64(0);
692 : : cmd23 = vsetq_lane_u64((((uint64_t)RTE_EVENT_TYPE_CPU << 28) | tag |
693 : : CNXK_ETHDEV_SEC_OUTB_EV_SUB << 20), cmd23, 0);
694 : : cmd23 = vsetq_lane_u64((uintptr_t)m | 1, cmd23, 1);
695 : :
696 : : /* Move to our line */
697 : : laddr = LMT_OFF(lbase, *lnum, *loff ? 64 : 0);
698 : :
699 : : /* Write CPT instruction to lmt line */
700 : : vst1q_u64(laddr, cmd01);
701 : : vst1q_u64((laddr + 2), cmd23);
702 : :
703 : : *(__uint128_t *)(laddr + 4) = *(__uint128_t *)ucode_cmd;
704 : : *(__uint128_t *)(laddr + 6) = *(__uint128_t *)(ucode_cmd + 2);
705 : :
706 : : /* Move to next line for every other CPT inst */
707 : : *loff = !(*loff);
708 : : *lnum = *lnum + (*loff ? 0 : 1);
709 : : *shft = *shft + (*loff ? 0 : 3);
710 : : }
711 : :
712 : : #else
713 : :
714 : : static __rte_always_inline void
715 : : cn20k_nix_prep_sec(struct rte_mbuf *m, uint64_t *cmd, uintptr_t *nixtx_addr, uintptr_t lbase,
716 : : uint8_t *lnum, uint8_t *loff, uint8_t *shft, uint64_t sa_base,
717 : : const uint16_t flags)
718 : : {
719 : : RTE_SET_USED(m);
720 : : RTE_SET_USED(cmd);
721 : : RTE_SET_USED(nixtx_addr);
722 : : RTE_SET_USED(lbase);
723 : : RTE_SET_USED(lnum);
724 : : RTE_SET_USED(loff);
725 : : RTE_SET_USED(shft);
726 : : RTE_SET_USED(sa_base);
727 : : RTE_SET_USED(flags);
728 : : }
729 : : #endif
730 : :
731 : : static inline void
732 : 0 : cn20k_nix_free_extmbuf(struct rte_mbuf *m)
733 : : {
734 : : struct rte_mbuf *m_next;
735 [ # # ]: 0 : while (m != NULL) {
736 : 0 : m_next = m->next;
737 : : rte_pktmbuf_free_seg(m);
738 : : m = m_next;
739 : : }
740 : 0 : }
741 : :
742 : : static __rte_always_inline uint64_t
743 : : cn20k_nix_prefree_seg(struct rte_mbuf *m, struct rte_mbuf **extm, struct cn20k_eth_txq *txq,
744 : : struct nix_send_hdr_s *send_hdr, uint64_t *aura)
745 : : {
746 : : struct rte_mbuf *prev = NULL;
747 : : uint32_t sqe_id;
748 : :
749 [ # # # # ]: 0 : if (RTE_MBUF_HAS_EXTBUF(m)) {
750 [ # # # # : 0 : if (unlikely(txq->tx_compl.ena == 0)) {
# # # # ]
751 : 0 : m->next = *extm;
752 : : *extm = m;
753 : 0 : return 1;
754 : : }
755 [ # # # # : 0 : if (send_hdr->w0.pnc) {
# # # # ]
756 : 0 : sqe_id = send_hdr->w1.sqe_id;
757 : 0 : prev = txq->tx_compl.ptr[sqe_id];
758 : 0 : m->next = prev;
759 : 0 : txq->tx_compl.ptr[sqe_id] = m;
760 : : } else {
761 : 0 : sqe_id = rte_atomic_fetch_add_explicit(&txq->tx_compl.sqe_id, 1,
762 : : rte_memory_order_relaxed);
763 : 0 : send_hdr->w0.pnc = 1;
764 : 0 : send_hdr->w1.sqe_id = sqe_id & txq->tx_compl.nb_desc_mask;
765 : 0 : txq->tx_compl.ptr[send_hdr->w1.sqe_id] = m;
766 : : }
767 : : return 1;
768 : : } else {
769 : : return cnxk_nix_prefree_seg(m, aura);
770 : : }
771 : : }
772 : :
773 : : #if defined(RTE_ARCH_ARM64)
774 : : /* Only called for first segments of single segmented mbufs */
775 : : static __rte_always_inline void
776 : : cn20k_nix_prefree_seg_vec(struct rte_mbuf **mbufs, struct rte_mbuf **extm,
777 : : struct cn20k_eth_txq *txq, uint64x2_t *senddesc01_w0,
778 : : uint64x2_t *senddesc23_w0, uint64x2_t *senddesc01_w1,
779 : : uint64x2_t *senddesc23_w1)
780 : : {
781 : : struct rte_mbuf **tx_compl_ptr = txq->tx_compl.ptr;
782 : : uint32_t nb_desc_mask = txq->tx_compl.nb_desc_mask;
783 : : bool tx_compl_ena = txq->tx_compl.ena;
784 : : struct rte_mbuf *m0, *m1, *m2, *m3;
785 : : struct rte_mbuf *cookie;
786 : : uint64_t w0, w1, aura;
787 : : uint64_t sqe_id;
788 : :
789 : : m0 = mbufs[0];
790 : : m1 = mbufs[1];
791 : : m2 = mbufs[2];
792 : : m3 = mbufs[3];
793 : :
794 : : /* mbuf 0 */
795 : : w0 = vgetq_lane_u64(*senddesc01_w0, 0);
796 : : if (RTE_MBUF_HAS_EXTBUF(m0)) {
797 : : w0 |= BIT_ULL(19);
798 : : w1 = vgetq_lane_u64(*senddesc01_w1, 0);
799 : : w1 &= ~0xFFFF000000000000UL;
800 : : if (unlikely(!tx_compl_ena)) {
801 : : m0->next = *extm;
802 : : *extm = m0;
803 : : } else {
804 : : sqe_id = rte_atomic_fetch_add_explicit(&txq->tx_compl.sqe_id, 1,
805 : : rte_memory_order_relaxed);
806 : : sqe_id = sqe_id & nb_desc_mask;
807 : : /* Set PNC */
808 : : w0 |= BIT_ULL(43);
809 : : w1 |= sqe_id << 48;
810 : : tx_compl_ptr[sqe_id] = m0;
811 : : *senddesc01_w1 = vsetq_lane_u64(w1, *senddesc01_w1, 0);
812 : : }
813 : : } else {
814 : : cookie = RTE_MBUF_DIRECT(m0) ? m0 : rte_mbuf_from_indirect(m0);
815 : : aura = (w0 >> 20) & 0xFFFFF;
816 : : w0 &= ~0xFFFFF00000UL;
817 : : w0 |= cnxk_nix_prefree_seg(m0, &aura) << 19;
818 : : w0 |= aura << 20;
819 : :
820 : : if ((w0 & BIT_ULL(19)) == 0)
821 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
822 : : }
823 : : *senddesc01_w0 = vsetq_lane_u64(w0, *senddesc01_w0, 0);
824 : :
825 : : /* mbuf1 */
826 : : w0 = vgetq_lane_u64(*senddesc01_w0, 1);
827 : : if (RTE_MBUF_HAS_EXTBUF(m1)) {
828 : : w0 |= BIT_ULL(19);
829 : : w1 = vgetq_lane_u64(*senddesc01_w1, 1);
830 : : w1 &= ~0xFFFF000000000000UL;
831 : : if (unlikely(!tx_compl_ena)) {
832 : : m1->next = *extm;
833 : : *extm = m1;
834 : : } else {
835 : : sqe_id = rte_atomic_fetch_add_explicit(&txq->tx_compl.sqe_id, 1,
836 : : rte_memory_order_relaxed);
837 : : sqe_id = sqe_id & nb_desc_mask;
838 : : /* Set PNC */
839 : : w0 |= BIT_ULL(43);
840 : : w1 |= sqe_id << 48;
841 : : tx_compl_ptr[sqe_id] = m1;
842 : : *senddesc01_w1 = vsetq_lane_u64(w1, *senddesc01_w1, 1);
843 : : }
844 : : } else {
845 : : cookie = RTE_MBUF_DIRECT(m1) ? m1 : rte_mbuf_from_indirect(m1);
846 : : aura = (w0 >> 20) & 0xFFFFF;
847 : : w0 &= ~0xFFFFF00000UL;
848 : : w0 |= cnxk_nix_prefree_seg(m1, &aura) << 19;
849 : : w0 |= aura << 20;
850 : :
851 : : if ((w0 & BIT_ULL(19)) == 0)
852 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
853 : : }
854 : : *senddesc01_w0 = vsetq_lane_u64(w0, *senddesc01_w0, 1);
855 : :
856 : : /* mbuf 2 */
857 : : w0 = vgetq_lane_u64(*senddesc23_w0, 0);
858 : : if (RTE_MBUF_HAS_EXTBUF(m2)) {
859 : : w0 |= BIT_ULL(19);
860 : : w1 = vgetq_lane_u64(*senddesc23_w1, 0);
861 : : w1 &= ~0xFFFF000000000000UL;
862 : : if (unlikely(!tx_compl_ena)) {
863 : : m2->next = *extm;
864 : : *extm = m2;
865 : : } else {
866 : : sqe_id = rte_atomic_fetch_add_explicit(&txq->tx_compl.sqe_id, 1,
867 : : rte_memory_order_relaxed);
868 : : sqe_id = sqe_id & nb_desc_mask;
869 : : /* Set PNC */
870 : : w0 |= BIT_ULL(43);
871 : : w1 |= sqe_id << 48;
872 : : tx_compl_ptr[sqe_id] = m2;
873 : : *senddesc23_w1 = vsetq_lane_u64(w1, *senddesc23_w1, 0);
874 : : }
875 : : } else {
876 : : cookie = RTE_MBUF_DIRECT(m2) ? m2 : rte_mbuf_from_indirect(m2);
877 : : aura = (w0 >> 20) & 0xFFFFF;
878 : : w0 &= ~0xFFFFF00000UL;
879 : : w0 |= cnxk_nix_prefree_seg(m2, &aura) << 19;
880 : : w0 |= aura << 20;
881 : :
882 : : if ((w0 & BIT_ULL(19)) == 0)
883 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
884 : : }
885 : : *senddesc23_w0 = vsetq_lane_u64(w0, *senddesc23_w0, 0);
886 : :
887 : : /* mbuf3 */
888 : : w0 = vgetq_lane_u64(*senddesc23_w0, 1);
889 : : if (RTE_MBUF_HAS_EXTBUF(m3)) {
890 : : w0 |= BIT_ULL(19);
891 : : w1 = vgetq_lane_u64(*senddesc23_w1, 1);
892 : : w1 &= ~0xFFFF000000000000UL;
893 : : if (unlikely(!tx_compl_ena)) {
894 : : m3->next = *extm;
895 : : *extm = m3;
896 : : } else {
897 : : sqe_id = rte_atomic_fetch_add_explicit(&txq->tx_compl.sqe_id, 1,
898 : : rte_memory_order_relaxed);
899 : : sqe_id = sqe_id & nb_desc_mask;
900 : : /* Set PNC */
901 : : w0 |= BIT_ULL(43);
902 : : w1 |= sqe_id << 48;
903 : : tx_compl_ptr[sqe_id] = m3;
904 : : *senddesc23_w1 = vsetq_lane_u64(w1, *senddesc23_w1, 1);
905 : : }
906 : : } else {
907 : : cookie = RTE_MBUF_DIRECT(m3) ? m3 : rte_mbuf_from_indirect(m3);
908 : : aura = (w0 >> 20) & 0xFFFFF;
909 : : w0 &= ~0xFFFFF00000UL;
910 : : w0 |= cnxk_nix_prefree_seg(m3, &aura) << 19;
911 : : w0 |= aura << 20;
912 : :
913 : : if ((w0 & BIT_ULL(19)) == 0)
914 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
915 : : }
916 : : *senddesc23_w0 = vsetq_lane_u64(w0, *senddesc23_w0, 1);
917 : : #ifndef RTE_LIBRTE_MEMPOOL_DEBUG
918 : : RTE_SET_USED(cookie);
919 : : #endif
920 : : }
921 : : #endif
922 : :
923 : : static __rte_always_inline void
924 : : cn20k_nix_xmit_prepare_tso(struct rte_mbuf *m, const uint64_t flags)
925 : : {
926 : 0 : uint64_t mask, ol_flags = m->ol_flags;
927 : :
928 [ # # ]: 0 : if (flags & NIX_TX_OFFLOAD_TSO_F && (ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
929 : 0 : uintptr_t mdata = rte_pktmbuf_mtod(m, uintptr_t);
930 : : uint16_t *iplen, *oiplen, *oudplen;
931 : : uint16_t lso_sb, paylen;
932 : :
933 : 0 : mask = -!!(ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IPV6));
934 : 0 : lso_sb = (mask & (m->outer_l2_len + m->outer_l3_len)) + m->l2_len + m->l3_len +
935 : 0 : m->l4_len;
936 : :
937 : : /* Reduce payload len from base headers */
938 : 0 : paylen = m->pkt_len - lso_sb;
939 : :
940 : : /* Get iplen position assuming no tunnel hdr */
941 [ # # ]: 0 : iplen = (uint16_t *)(mdata + m->l2_len + (2 << !!(ol_flags & RTE_MBUF_F_TX_IPV6)));
942 : : /* Handle tunnel tso */
943 : 0 : if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) &&
944 [ # # ]: 0 : (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)) {
945 : 0 : const uint8_t is_udp_tun =
946 : 0 : (CNXK_NIX_UDP_TUN_BITMASK >>
947 : 0 : ((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) >> 45)) &
948 : : 0x1;
949 : :
950 : 0 : oiplen = (uint16_t *)(mdata + m->outer_l2_len +
951 [ # # ]: 0 : (2 << !!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV6)));
952 [ # # ]: 0 : *oiplen = rte_cpu_to_be_16(rte_be_to_cpu_16(*oiplen) - paylen);
953 : :
954 : : /* Update format for UDP tunneled packet */
955 [ # # ]: 0 : if (is_udp_tun) {
956 : 0 : oudplen =
957 : 0 : (uint16_t *)(mdata + m->outer_l2_len + m->outer_l3_len + 4);
958 [ # # ]: 0 : *oudplen = rte_cpu_to_be_16(rte_be_to_cpu_16(*oudplen) - paylen);
959 : : }
960 : :
961 : : /* Update iplen position to inner ip hdr */
962 : 0 : iplen = (uint16_t *)(mdata + lso_sb - m->l3_len - m->l4_len +
963 : : (2 << !!(ol_flags & RTE_MBUF_F_TX_IPV6)));
964 : : }
965 : :
966 [ # # ]: 0 : *iplen = rte_cpu_to_be_16(rte_be_to_cpu_16(*iplen) - paylen);
967 : : }
968 : : }
969 : :
970 : : static __rte_always_inline void
971 : : cn20k_nix_xmit_prepare(struct cn20k_eth_txq *txq, struct rte_mbuf *m, struct rte_mbuf **extm,
972 : : uint64_t *cmd, const uint16_t flags, const uint64_t lso_tun_fmt, bool *sec,
973 : : uint8_t mark_flag, uint64_t mark_fmt)
974 : : {
975 : : uint8_t mark_off = 0, mark_vlan = 0, markptr = 0;
976 : : struct nix_send_ext_s *send_hdr_ext;
977 : : struct nix_send_hdr_s *send_hdr;
978 : : uint64_t ol_flags = 0, mask;
979 : : union nix_send_hdr_w1_u w1;
980 : : union nix_send_sg_s *sg;
981 : : uint16_t mark_form = 0;
982 : :
983 : : send_hdr = (struct nix_send_hdr_s *)cmd;
984 : : if (flags & NIX_TX_NEED_EXT_HDR) {
985 : : send_hdr_ext = (struct nix_send_ext_s *)(cmd + 2);
986 : : sg = (union nix_send_sg_s *)(cmd + 4);
987 : : /* Clear previous markings */
988 : 0 : send_hdr_ext->w0.lso = 0;
989 : : send_hdr_ext->w0.mark_en = 0;
990 : 0 : send_hdr_ext->w1.u = 0;
991 : : ol_flags = m->ol_flags;
992 : : } else {
993 : : sg = (union nix_send_sg_s *)(cmd + 2);
994 : : }
995 : :
996 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F)
997 : 0 : send_hdr->w0.pnc = 0;
998 : :
999 : : if (flags & (NIX_TX_NEED_SEND_HDR_W1 | NIX_TX_OFFLOAD_SECURITY_F)) {
1000 : 0 : ol_flags = m->ol_flags;
1001 : 0 : w1.u = 0;
1002 : : }
1003 : :
1004 : : if (!(flags & NIX_TX_MULTI_SEG_F))
1005 : : send_hdr->w0.total = m->data_len;
1006 : : else
1007 : 0 : send_hdr->w0.total = m->pkt_len;
1008 [ # # # # ]: 0 : send_hdr->w0.aura = roc_npa_aura_handle_to_aura(m->pool->pool_id);
1009 : :
1010 : : /*
1011 : : * L3type: 2 => IPV4
1012 : : * 3 => IPV4 with csum
1013 : : * 4 => IPV6
1014 : : * L3type and L3ptr needs to be set for either
1015 : : * L3 csum or L4 csum or LSO
1016 : : *
1017 : : */
1018 : :
1019 : : if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) && (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) {
1020 : 0 : const uint8_t csum = !!(ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM);
1021 : 0 : const uint8_t ol3type = ((!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV4)) << 1) +
1022 : : ((!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV6)) << 2) +
1023 : 0 : !!(ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM);
1024 : :
1025 : : /* Outer L3 */
1026 : 0 : w1.ol3type = ol3type;
1027 [ # # ]: 0 : mask = 0xffffull << ((!!ol3type) << 4);
1028 : 0 : w1.ol3ptr = ~mask & m->outer_l2_len;
1029 : 0 : w1.ol4ptr = ~mask & (w1.ol3ptr + m->outer_l3_len);
1030 : :
1031 : : /* Outer L4 */
1032 : 0 : w1.ol4type = csum + (csum << 1);
1033 : :
1034 : : /* Inner L3 */
1035 : 0 : w1.il3type = ((!!(ol_flags & RTE_MBUF_F_TX_IPV4)) << 1) +
1036 : : ((!!(ol_flags & RTE_MBUF_F_TX_IPV6)) << 2);
1037 : 0 : w1.il3ptr = w1.ol4ptr + m->l2_len;
1038 : 0 : w1.il4ptr = w1.il3ptr + m->l3_len;
1039 : : /* Increment it by 1 if it is IPV4 as 3 is with csum */
1040 : 0 : w1.il3type = w1.il3type + !!(ol_flags & RTE_MBUF_F_TX_IP_CKSUM);
1041 : :
1042 : : /* Inner L4 */
1043 : 0 : w1.il4type = (ol_flags & RTE_MBUF_F_TX_L4_MASK) >> 52;
1044 : :
1045 : : /* In case of no tunnel header use only
1046 : : * shift IL3/IL4 fields a bit to use
1047 : : * OL3/OL4 for header checksum
1048 : : */
1049 : 0 : mask = !ol3type;
1050 : 0 : w1.u = ((w1.u & 0xFFFFFFFF00000000) >> (mask << 3)) |
1051 : 0 : ((w1.u & 0X00000000FFFFFFFF) >> (mask << 4));
1052 : :
1053 : : } else if (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) {
1054 : : const uint8_t csum = !!(ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM);
1055 : : const uint8_t outer_l2_len = m->outer_l2_len;
1056 : :
1057 : : /* Outer L3 */
1058 : : w1.ol3ptr = outer_l2_len;
1059 : : w1.ol4ptr = outer_l2_len + m->outer_l3_len;
1060 : : /* Increment it by 1 if it is IPV4 as 3 is with csum */
1061 : : w1.ol3type = ((!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV4)) << 1) +
1062 : : ((!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV6)) << 2) +
1063 : : !!(ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM);
1064 : :
1065 : : /* Outer L4 */
1066 : : w1.ol4type = csum + (csum << 1);
1067 : :
1068 : : } else if (flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) {
1069 : 0 : const uint8_t l2_len = m->l2_len;
1070 : :
1071 : : /* Always use OLXPTR and OLXTYPE when only
1072 : : * when one header is present
1073 : : */
1074 : :
1075 : : /* Inner L3 */
1076 : 0 : w1.ol3ptr = l2_len;
1077 : 0 : w1.ol4ptr = l2_len + m->l3_len;
1078 : : /* Increment it by 1 if it is IPV4 as 3 is with csum */
1079 : 0 : w1.ol3type = ((!!(ol_flags & RTE_MBUF_F_TX_IPV4)) << 1) +
1080 : 0 : ((!!(ol_flags & RTE_MBUF_F_TX_IPV6)) << 2) +
1081 : 0 : !!(ol_flags & RTE_MBUF_F_TX_IP_CKSUM);
1082 : :
1083 : : /* Inner L4 */
1084 : 0 : w1.ol4type = (ol_flags & RTE_MBUF_F_TX_L4_MASK) >> 52;
1085 : : }
1086 : :
1087 : : if (flags & NIX_TX_NEED_EXT_HDR && flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
1088 : 0 : const uint8_t ipv6 = !!(ol_flags & RTE_MBUF_F_TX_IPV6);
1089 : 0 : const uint8_t ip = !!(ol_flags & (RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IPV6));
1090 : :
1091 : 0 : send_hdr_ext->w1.vlan1_ins_ena = !!(ol_flags & RTE_MBUF_F_TX_VLAN);
1092 : : /* HW will update ptr after vlan0 update */
1093 : 0 : send_hdr_ext->w1.vlan1_ins_ptr = 12;
1094 : 0 : send_hdr_ext->w1.vlan1_ins_tci = m->vlan_tci;
1095 : :
1096 : 0 : send_hdr_ext->w1.vlan0_ins_ena = !!(ol_flags & RTE_MBUF_F_TX_QINQ);
1097 : : /* 2B before end of l2 header */
1098 : 0 : send_hdr_ext->w1.vlan0_ins_ptr = 12;
1099 : 0 : send_hdr_ext->w1.vlan0_ins_tci = m->vlan_tci_outer;
1100 : : /* Fill for VLAN marking only when VLAN insertion enabled */
1101 : 0 : mark_vlan = ((mark_flag & CNXK_TM_MARK_VLAN_DEI) &
1102 : 0 : (send_hdr_ext->w1.vlan1_ins_ena || send_hdr_ext->w1.vlan0_ins_ena));
1103 : :
1104 : : /* Mask requested flags with packet data information */
1105 : 0 : mark_off = mark_flag & ((ip << 2) | (ip << 1) | mark_vlan);
1106 : 0 : mark_off = ffs(mark_off & CNXK_TM_MARK_MASK);
1107 : :
1108 : 0 : mark_form = (mark_fmt >> ((mark_off - !!mark_off) << 4));
1109 : 0 : mark_form = (mark_form >> (ipv6 << 3)) & 0xFF;
1110 : 0 : markptr = m->l2_len + (mark_form >> 7) - (mark_vlan << 2);
1111 : :
1112 : 0 : send_hdr_ext->w0.mark_en = !!mark_off;
1113 : 0 : send_hdr_ext->w0.markform = mark_form & 0x7F;
1114 : 0 : send_hdr_ext->w0.markptr = markptr;
1115 : : }
1116 : :
1117 [ # # ]: 0 : if (flags & NIX_TX_NEED_EXT_HDR && flags & NIX_TX_OFFLOAD_TSO_F &&
1118 : : (ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
1119 : : uint16_t lso_sb;
1120 : : uint64_t mask;
1121 : :
1122 : 0 : mask = -(!w1.il3type);
1123 : 0 : lso_sb = (mask & w1.ol4ptr) + (~mask & w1.il4ptr) + m->l4_len;
1124 : :
1125 : 0 : send_hdr_ext->w0.lso_sb = lso_sb;
1126 : 0 : send_hdr_ext->w0.lso = 1;
1127 : 0 : send_hdr_ext->w0.lso_mps = m->tso_segsz;
1128 : 0 : send_hdr_ext->w0.lso_format =
1129 : 0 : NIX_LSO_FORMAT_IDX_TSOV4 + !!(ol_flags & RTE_MBUF_F_TX_IPV6);
1130 : 0 : w1.ol4type = NIX_SENDL4TYPE_TCP_CKSUM;
1131 : :
1132 : : /* Handle tunnel tso */
1133 : 0 : if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) &&
1134 [ # # ]: 0 : (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)) {
1135 : 0 : const uint8_t is_udp_tun =
1136 : 0 : (CNXK_NIX_UDP_TUN_BITMASK >>
1137 : 0 : ((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) >> 45)) &
1138 : : 0x1;
1139 [ # # ]: 0 : uint8_t shift = is_udp_tun ? 32 : 0;
1140 : :
1141 : 0 : shift += (!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV6) << 4);
1142 : 0 : shift += (!!(ol_flags & RTE_MBUF_F_TX_IPV6) << 3);
1143 : :
1144 : 0 : w1.il4type = NIX_SENDL4TYPE_TCP_CKSUM;
1145 [ # # ]: 0 : w1.ol4type = is_udp_tun ? NIX_SENDL4TYPE_UDP_CKSUM : 0;
1146 : : /* Update format for UDP tunneled packet */
1147 : 0 : send_hdr_ext->w0.lso_format = (lso_tun_fmt >> shift);
1148 : : }
1149 : : }
1150 : :
1151 : : if (flags & NIX_TX_NEED_SEND_HDR_W1)
1152 : 0 : send_hdr->w1.u = w1.u;
1153 : :
1154 : : if (!(flags & NIX_TX_MULTI_SEG_F)) {
1155 : : struct rte_mbuf *cookie;
1156 : :
1157 : : sg->seg1_size = send_hdr->w0.total;
1158 : : *(rte_iova_t *)(sg + 1) = rte_mbuf_data_iova(m);
1159 : : cookie = RTE_MBUF_DIRECT(m) ? m : rte_mbuf_from_indirect(m);
1160 : :
1161 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
1162 : : uint64_t aura;
1163 : :
1164 : : /* DF bit = 1 if refcount of current mbuf or parent mbuf
1165 : : * is greater than 1
1166 : : * DF bit = 0 otherwise
1167 : : */
1168 : : aura = send_hdr->w0.aura;
1169 : : send_hdr->w0.df = cn20k_nix_prefree_seg(m, extm, txq, send_hdr, &aura);
1170 : : send_hdr->w0.aura = aura;
1171 : : }
1172 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1173 : : /* Mark mempool object as "put" since it is freed by NIX */
1174 : : if (!send_hdr->w0.df)
1175 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
1176 : : #else
1177 : : RTE_SET_USED(cookie);
1178 : : #endif
1179 : : } else {
1180 [ # # # # ]: 0 : sg->seg1_size = m->data_len;
1181 : : *(rte_iova_t *)(sg + 1) = rte_mbuf_data_iova(m);
1182 : :
1183 : : /* NOFF is handled later for multi-seg */
1184 : : }
1185 : :
1186 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F)
1187 : 0 : *sec = !!(ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD);
1188 : : }
1189 : :
1190 : : static __rte_always_inline void
1191 : : cn20k_nix_xmit_mv_lmt_base(uintptr_t lmt_addr, uint64_t *cmd, const uint16_t flags)
1192 : : {
1193 : : struct nix_send_ext_s *send_hdr_ext;
1194 : : union nix_send_sg_s *sg;
1195 : :
1196 : : /* With minimal offloads, 'cmd' being local could be optimized out to
1197 : : * registers. In other cases, 'cmd' will be in stack. Intent is
1198 : : * 'cmd' stores content from txq->cmd which is copied only once.
1199 : : */
1200 : 0 : *((struct nix_send_hdr_s *)lmt_addr) = *(struct nix_send_hdr_s *)cmd;
1201 : 0 : lmt_addr += 16;
1202 : : if (flags & NIX_TX_NEED_EXT_HDR) {
1203 : : send_hdr_ext = (struct nix_send_ext_s *)(cmd + 2);
1204 : 0 : *((struct nix_send_ext_s *)lmt_addr) = *send_hdr_ext;
1205 : 0 : lmt_addr += 16;
1206 : :
1207 : : sg = (union nix_send_sg_s *)(cmd + 4);
1208 : : } else {
1209 : : sg = (union nix_send_sg_s *)(cmd + 2);
1210 : : }
1211 : : /* In case of multi-seg, sg template is stored here */
1212 : 0 : *((union nix_send_sg_s *)lmt_addr) = *sg;
1213 : 0 : *(rte_iova_t *)(lmt_addr + 8) = *(rte_iova_t *)(sg + 1);
1214 : : }
1215 : :
1216 : : static __rte_always_inline void
1217 : : cn20k_nix_xmit_prepare_tstamp(struct cn20k_eth_txq *txq, uintptr_t lmt_addr,
1218 : : const uint64_t ol_flags, const uint16_t no_segdw,
1219 : : const uint16_t flags)
1220 : : {
1221 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
1222 : 0 : const uint8_t is_ol_tstamp = !(ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST);
1223 : : uint64_t *lmt = (uint64_t *)lmt_addr;
1224 : 0 : uint16_t off = (no_segdw - 1) << 1;
1225 : : struct nix_send_mem_s *send_mem;
1226 : :
1227 : 0 : send_mem = (struct nix_send_mem_s *)(lmt + off);
1228 : : /* Packets for which PKT_TX_IEEE1588_TMST is not set, tx tstamp
1229 : : * should not be recorded, hence changing the alg type to
1230 : : * NIX_SENDMEMALG_SUB and also changing send mem addr field to
1231 : : * next 8 bytes as it corrupts the actual Tx tstamp registered
1232 : : * address.
1233 : : */
1234 : 0 : send_mem->w0.subdc = NIX_SUBDC_MEM;
1235 : 0 : send_mem->w0.alg = NIX_SENDMEMALG_SETTSTMP + (is_ol_tstamp << 3);
1236 [ # # ]: 0 : send_mem->addr = (rte_iova_t)(((uint64_t *)txq->ts_mem) + is_ol_tstamp);
1237 : : }
1238 : : }
1239 : :
1240 : : static __rte_always_inline uint16_t
1241 : : cn20k_nix_prepare_mseg(struct cn20k_eth_txq *txq, struct rte_mbuf *m, struct rte_mbuf **extm,
1242 : : uint64_t *cmd, const uint16_t flags)
1243 : : {
1244 : : uint64_t prefree = 0, aura0, aura, nb_segs, segdw;
1245 : : struct nix_send_hdr_s *send_hdr;
1246 : : union nix_send_sg_s *sg, l_sg;
1247 : : union nix_send_sg2_s l_sg2;
1248 : : struct rte_mbuf *cookie;
1249 : : struct rte_mbuf *m_next;
1250 : : uint8_t off, is_sg2;
1251 : : uint64_t len, dlen;
1252 : : uint64_t ol_flags;
1253 : : uint64_t *slist;
1254 : :
1255 : : send_hdr = (struct nix_send_hdr_s *)cmd;
1256 : :
1257 : : if (flags & NIX_TX_NEED_EXT_HDR)
1258 : : off = 2;
1259 : : else
1260 : : off = 0;
1261 : :
1262 : 0 : sg = (union nix_send_sg_s *)&cmd[2 + off];
1263 : 0 : len = send_hdr->w0.total;
1264 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F)
1265 : 0 : ol_flags = m->ol_flags;
1266 : :
1267 : : /* Start from second segment, first segment is already there */
1268 : 0 : dlen = m->data_len;
1269 : : is_sg2 = 0;
1270 : 0 : l_sg.u = sg->u;
1271 : : /* Clear l_sg.u first seg length that might be stale from vector path */
1272 : 0 : l_sg.u &= ~0xFFFFUL;
1273 : 0 : l_sg.u |= dlen;
1274 : 0 : len -= dlen;
1275 : 0 : nb_segs = m->nb_segs - 1;
1276 : 0 : m_next = m->next;
1277 : 0 : m->next = NULL;
1278 : 0 : m->nb_segs = 1;
1279 : 0 : slist = &cmd[3 + off + 1];
1280 : :
1281 : : cookie = RTE_MBUF_DIRECT(m) ? m : rte_mbuf_from_indirect(m);
1282 : : /* Set invert df if buffer is not to be freed by H/W */
1283 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
1284 [ # # # # ]: 0 : aura = send_hdr->w0.aura;
1285 : : prefree = cn20k_nix_prefree_seg(m, extm, txq, send_hdr, &aura);
1286 : 0 : send_hdr->w0.aura = aura;
1287 : 0 : l_sg.i1 = prefree;
1288 : : }
1289 : :
1290 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1291 : : /* Mark mempool object as "put" since it is freed by NIX */
1292 : : if (!prefree)
1293 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
1294 : : rte_io_wmb();
1295 : : #else
1296 : : RTE_SET_USED(cookie);
1297 : : #endif
1298 : :
1299 : : /* Quickly handle single segmented packets. With this if-condition
1300 : : * compiler will completely optimize out the below do-while loop
1301 : : * from the Tx handler when NIX_TX_MULTI_SEG_F offload is not set.
1302 : : */
1303 : : if (!(flags & NIX_TX_MULTI_SEG_F))
1304 : : goto done;
1305 : :
1306 : : aura0 = send_hdr->w0.aura;
1307 : : m = m_next;
1308 [ # # # # ]: 0 : if (!m)
1309 : 0 : goto done;
1310 : :
1311 : : /* Fill mbuf segments */
1312 : : do {
1313 : : uint64_t iova;
1314 : :
1315 : : /* Save the current mbuf properties. These can get cleared in
1316 : : * cnxk_nix_prefree_seg()
1317 : : */
1318 [ # # # # ]: 0 : m_next = m->next;
1319 : : iova = rte_mbuf_data_iova(m);
1320 : 0 : dlen = m->data_len;
1321 : 0 : len -= dlen;
1322 : :
1323 : 0 : nb_segs--;
1324 : : aura = aura0;
1325 : : prefree = 0;
1326 : :
1327 : 0 : m->next = NULL;
1328 : :
1329 : : cookie = RTE_MBUF_DIRECT(m) ? m : rte_mbuf_from_indirect(m);
1330 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
1331 [ # # # # ]: 0 : aura = roc_npa_aura_handle_to_aura(m->pool->pool_id);
1332 : : prefree = cn20k_nix_prefree_seg(m, extm, txq, send_hdr, &aura);
1333 [ # # # # : 0 : is_sg2 = aura != aura0 && !prefree;
# # # # ]
1334 : : }
1335 : :
1336 [ # # # # ]: 0 : if (unlikely(is_sg2)) {
1337 : : /* This mbuf belongs to a different pool and
1338 : : * DF bit is not to be set, so use SG2 subdesc
1339 : : * so that it is freed to the appropriate pool.
1340 : : */
1341 : :
1342 : : /* Write the previous descriptor out */
1343 : 0 : sg->u = l_sg.u;
1344 : :
1345 : : /* If the current SG subdc does not have any
1346 : : * iovas in it, then the SG2 subdc can overwrite
1347 : : * that SG subdc.
1348 : : *
1349 : : * If the current SG subdc has 2 iovas in it, then
1350 : : * the current iova word should be left empty.
1351 : : */
1352 : 0 : slist += (-1 + (int)l_sg.segs);
1353 : : sg = (union nix_send_sg_s *)slist;
1354 : :
1355 : 0 : l_sg2.u = l_sg.u & 0xC00000000000000; /* LD_TYPE */
1356 : 0 : l_sg2.subdc = NIX_SUBDC_SG2;
1357 : 0 : l_sg2.aura = aura;
1358 : 0 : l_sg2.seg1_size = dlen;
1359 : 0 : l_sg.u = l_sg2.u;
1360 : :
1361 : : slist++;
1362 : 0 : *slist = iova;
1363 : 0 : slist++;
1364 : : } else {
1365 : 0 : *slist = iova;
1366 : : /* Set invert df if buffer is not to be freed by H/W */
1367 : 0 : l_sg.u |= (prefree << (l_sg.segs + 55));
1368 : : /* Set the segment length */
1369 : 0 : l_sg.u |= ((uint64_t)dlen << (l_sg.segs << 4));
1370 : 0 : l_sg.segs += 1;
1371 : 0 : slist++;
1372 : : }
1373 : :
1374 [ # # # # : 0 : if ((is_sg2 || l_sg.segs > 2) && nb_segs) {
# # # # #
# # # ]
1375 : 0 : sg->u = l_sg.u;
1376 : : /* Next SG subdesc */
1377 : : sg = (union nix_send_sg_s *)slist;
1378 : 0 : l_sg.u &= 0xC00000000000000; /* LD_TYPE */
1379 : 0 : l_sg.subdc = NIX_SUBDC_SG;
1380 : 0 : slist++;
1381 : : }
1382 : :
1383 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1384 : : /* Mark mempool object as "put" since it is freed by NIX
1385 : : */
1386 : : if (!prefree)
1387 : : RTE_MEMPOOL_CHECK_COOKIES(cookie->pool, (void **)&cookie, 1, 0);
1388 : : #else
1389 : : RTE_SET_USED(cookie);
1390 : : #endif
1391 : : m = m_next;
1392 [ # # # # ]: 0 : } while (nb_segs);
1393 : :
1394 : 0 : done:
1395 : : /* Add remaining bytes of security data to last seg */
1396 [ # # # # : 0 : if (flags & NIX_TX_OFFLOAD_SECURITY_F && ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD && len) {
# # # # ]
1397 [ # # # # ]: 0 : uint8_t shft = (l_sg.subdc == NIX_SUBDC_SG) ? ((l_sg.segs - 1) << 4) : 0;
1398 : :
1399 : 0 : dlen = ((l_sg.u >> shft) & 0xFFFFULL) + len;
1400 : 0 : l_sg.u = l_sg.u & ~(0xFFFFULL << shft);
1401 : 0 : l_sg.u |= dlen << shft;
1402 : : }
1403 : :
1404 : : /* Write the last subdc out */
1405 : 0 : sg->u = l_sg.u;
1406 : :
1407 : 0 : segdw = (uint64_t *)slist - (uint64_t *)&cmd[2 + off];
1408 : : /* Roundup extra dwords to multiple of 2 */
1409 : 0 : segdw = (segdw >> 1) + (segdw & 0x1);
1410 : : /* Default dwords */
1411 : 0 : segdw += (off >> 1) + 1 + !!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
1412 [ # # ]: 0 : send_hdr->w0.sizem1 = segdw - 1;
1413 : :
1414 [ # # ]: 0 : return segdw;
1415 : : }
1416 : :
1417 : : static __rte_always_inline uint16_t
1418 : : cn20k_nix_xmit_pkts(void *tx_queue, uint64_t *ws, struct rte_mbuf **tx_pkts, uint16_t pkts,
1419 : : uint64_t *cmd, const uint16_t flags)
1420 : : {
1421 : : struct cn20k_eth_txq *txq = tx_queue;
1422 : : const rte_iova_t io_addr = txq->io_addr;
1423 : : uint8_t lnum, c_lnum, c_shft, c_loff;
1424 : : uintptr_t pa, lbase = txq->lmt_base;
1425 : : uint16_t lmt_id, burst, left, i;
1426 : : struct rte_mbuf *extm = NULL;
1427 : : uintptr_t c_lbase = lbase;
1428 : : uint64_t lso_tun_fmt = 0;
1429 : : uint64_t mark_fmt = 0;
1430 : : uint8_t mark_flag = 0;
1431 : : rte_iova_t c_io_addr;
1432 : : uint16_t c_lmt_id;
1433 : : uint64_t sa_base;
1434 : : uintptr_t laddr;
1435 : : uint64_t data;
1436 : : bool sec;
1437 : :
1438 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && txq->tx_compl.ena)
1439 : : handle_tx_completion_pkts(txq, flags & NIX_TX_VWQE_F);
1440 : :
1441 : : if (!(flags & NIX_TX_VWQE_F))
1442 : : NIX_XMIT_FC_CHECK_RETURN(txq, pkts);
1443 : :
1444 : : /* Get cmd skeleton */
1445 : : cn20k_nix_tx_skeleton(txq, cmd, flags, !(flags & NIX_TX_VWQE_F));
1446 : :
1447 : : if (flags & NIX_TX_OFFLOAD_TSO_F)
1448 : : lso_tun_fmt = txq->lso_tun_fmt;
1449 : :
1450 : : if (flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
1451 : : mark_fmt = txq->mark_fmt;
1452 : : mark_flag = txq->mark_flag;
1453 : : }
1454 : :
1455 : : /* Get LMT base address and LMT ID as lcore id */
1456 : : ROC_LMT_BASE_ID_GET(lbase, lmt_id);
1457 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1458 : : ROC_LMT_CPT_BASE_ID_GET(c_lbase, c_lmt_id);
1459 : : c_io_addr = txq->cpt_io_addr;
1460 : : sa_base = txq->sa_base;
1461 : : }
1462 : :
1463 : : left = pkts;
1464 : : again:
1465 : : burst = left > 32 ? 32 : left;
1466 : :
1467 : : lnum = 0;
1468 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1469 : : c_lnum = 0;
1470 : : c_loff = 0;
1471 : : c_shft = 16;
1472 : : }
1473 : :
1474 : : for (i = 0; i < burst; i++) {
1475 : : /* Perform header writes for TSO, barrier at
1476 : : * lmt steorl will suffice.
1477 : : */
1478 : : if (flags & NIX_TX_OFFLOAD_TSO_F)
1479 : : cn20k_nix_xmit_prepare_tso(tx_pkts[i], flags);
1480 : :
1481 : : cn20k_nix_xmit_prepare(txq, tx_pkts[i], &extm, cmd, flags, lso_tun_fmt, &sec,
1482 : : mark_flag, mark_fmt);
1483 : :
1484 : : laddr = (uintptr_t)LMT_OFF(lbase, lnum, 0);
1485 : :
1486 : : /* Prepare CPT instruction and get nixtx addr */
1487 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F && sec)
1488 : : cn20k_nix_prep_sec(tx_pkts[i], cmd, &laddr, c_lbase, &c_lnum, &c_loff,
1489 : : &c_shft, sa_base, flags);
1490 : :
1491 : : /* Move NIX desc to LMT/NIXTX area */
1492 : : cn20k_nix_xmit_mv_lmt_base(laddr, cmd, flags);
1493 : : cn20k_nix_xmit_prepare_tstamp(txq, laddr, tx_pkts[i]->ol_flags, 4, flags);
1494 : : if (!(flags & NIX_TX_OFFLOAD_SECURITY_F) || !sec)
1495 : : lnum++;
1496 : : }
1497 : :
1498 : : if ((flags & NIX_TX_VWQE_F) && !(ws[3] & BIT_ULL(35)))
1499 : : ws[3] = roc_sso_hws_head_wait(ws[0]);
1500 : :
1501 : : left -= burst;
1502 : : tx_pkts += burst;
1503 : :
1504 : : /* Submit CPT instructions if any */
1505 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1506 : : uint16_t sec_pkts = ((c_lnum << 1) + c_loff);
1507 : :
1508 : : /* Reduce pkts to be sent to CPT */
1509 : : burst -= sec_pkts;
1510 : : if (flags & NIX_TX_VWQE_F)
1511 : : cn20k_nix_vwqe_wait_fc(txq, sec_pkts);
1512 : : cn20k_nix_sec_fc_wait(txq, sec_pkts);
1513 : : cn20k_nix_sec_steorl(c_io_addr, c_lmt_id, c_lnum, c_loff, c_shft);
1514 : : }
1515 : :
1516 : : /* Trigger LMTST */
1517 : : if (burst > 16) {
1518 : : data = cn20k_nix_tx_steor_data(flags);
1519 : : pa = io_addr | (data & 0x7) << 4;
1520 : : data &= ~0x7ULL;
1521 : : data |= (15ULL << 12);
1522 : : data |= (uint64_t)lmt_id;
1523 : :
1524 : : if (flags & NIX_TX_VWQE_F)
1525 : : cn20k_nix_vwqe_wait_fc(txq, 16);
1526 : : /* STEOR0 */
1527 : : roc_lmt_submit_steorl(data, pa);
1528 : :
1529 : : data = cn20k_nix_tx_steor_data(flags);
1530 : : pa = io_addr | (data & 0x7) << 4;
1531 : : data &= ~0x7ULL;
1532 : : data |= ((uint64_t)(burst - 17)) << 12;
1533 : : data |= (uint64_t)(lmt_id + 16);
1534 : :
1535 : : if (flags & NIX_TX_VWQE_F)
1536 : : cn20k_nix_vwqe_wait_fc(txq, burst - 16);
1537 : : /* STEOR1 */
1538 : : roc_lmt_submit_steorl(data, pa);
1539 : : } else if (burst) {
1540 : : data = cn20k_nix_tx_steor_data(flags);
1541 : : pa = io_addr | (data & 0x7) << 4;
1542 : : data &= ~0x7ULL;
1543 : : data |= ((uint64_t)(burst - 1)) << 12;
1544 : : data |= (uint64_t)lmt_id;
1545 : :
1546 : : if (flags & NIX_TX_VWQE_F)
1547 : : cn20k_nix_vwqe_wait_fc(txq, burst);
1548 : : /* STEOR0 */
1549 : : roc_lmt_submit_steorl(data, pa);
1550 : : }
1551 : :
1552 : : rte_io_wmb();
1553 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && !txq->tx_compl.ena) {
1554 : : cn20k_nix_free_extmbuf(extm);
1555 : : extm = NULL;
1556 : : }
1557 : :
1558 : : if (left)
1559 : : goto again;
1560 : :
1561 : : return pkts;
1562 : : }
1563 : :
1564 : : static __rte_always_inline uint16_t
1565 : : cn20k_nix_xmit_pkts_mseg(void *tx_queue, uint64_t *ws, struct rte_mbuf **tx_pkts, uint16_t pkts,
1566 : : uint64_t *cmd, const uint16_t flags)
1567 : : {
1568 : : struct cn20k_eth_txq *txq = tx_queue;
1569 : 0 : uintptr_t pa0, pa1, lbase = txq->lmt_base;
1570 : : const rte_iova_t io_addr = txq->io_addr;
1571 : : uint16_t segdw, lmt_id, burst, left, i;
1572 : : struct rte_mbuf *extm = NULL;
1573 : : uint8_t lnum, c_lnum, c_loff;
1574 : : uintptr_t c_lbase = lbase;
1575 : : uint64_t lso_tun_fmt = 0;
1576 : : uint64_t mark_fmt = 0;
1577 : : uint8_t mark_flag = 0;
1578 : : uint64_t data0, data1;
1579 : : rte_iova_t c_io_addr;
1580 : : uint8_t shft, c_shft;
1581 : : __uint128_t data128;
1582 : : uint16_t c_lmt_id;
1583 : : uint64_t sa_base;
1584 : : uintptr_t laddr;
1585 : : bool sec;
1586 : :
1587 [ # # ]: 0 : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && txq->tx_compl.ena)
1588 : 0 : handle_tx_completion_pkts(txq, flags & NIX_TX_VWQE_F);
1589 : :
1590 : : if (!(flags & NIX_TX_VWQE_F))
1591 [ # # # # : 0 : NIX_XMIT_FC_CHECK_RETURN(txq, pkts);
# # # # #
# # # #
# ]
1592 : :
1593 : : /* Get cmd skeleton */
1594 : : cn20k_nix_tx_skeleton(txq, cmd, flags, !(flags & NIX_TX_VWQE_F));
1595 : :
1596 : : if (flags & NIX_TX_OFFLOAD_TSO_F)
1597 : 0 : lso_tun_fmt = txq->lso_tun_fmt;
1598 : :
1599 : : if (flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
1600 : 0 : mark_fmt = txq->mark_fmt;
1601 : 0 : mark_flag = txq->mark_flag;
1602 : : }
1603 : :
1604 : : /* Get LMT base address and LMT ID as lcore id */
1605 : : ROC_LMT_BASE_ID_GET(lbase, lmt_id);
1606 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1607 : : ROC_LMT_CPT_BASE_ID_GET(c_lbase, c_lmt_id);
1608 : : c_io_addr = txq->cpt_io_addr;
1609 : : sa_base = txq->sa_base;
1610 : : }
1611 : :
1612 : : left = pkts;
1613 : : again:
1614 : 0 : burst = left > 32 ? 32 : left;
1615 : : shft = 16;
1616 : : data128 = 0;
1617 : :
1618 : : lnum = 0;
1619 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1620 : : c_lnum = 0;
1621 : : c_loff = 0;
1622 : : c_shft = 16;
1623 : : }
1624 : :
1625 [ # # ]: 0 : for (i = 0; i < burst; i++) {
1626 [ # # ]: 0 : cn20k_nix_tx_mbuf_validate(tx_pkts[i], flags);
1627 : :
1628 : : /* Perform header writes for TSO, barrier at
1629 : : * lmt steorl will suffice.
1630 : : */
1631 : : if (flags & NIX_TX_OFFLOAD_TSO_F)
1632 : : cn20k_nix_xmit_prepare_tso(tx_pkts[i], flags);
1633 : :
1634 : : cn20k_nix_xmit_prepare(txq, tx_pkts[i], &extm, cmd, flags, lso_tun_fmt, &sec,
1635 : : mark_flag, mark_fmt);
1636 : :
1637 [ # # ]: 0 : laddr = (uintptr_t)LMT_OFF(lbase, lnum, 0);
1638 : :
1639 : : /* Prepare CPT instruction and get nixtx addr */
1640 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F && sec)
1641 : : cn20k_nix_prep_sec(tx_pkts[i], cmd, &laddr, c_lbase, &c_lnum, &c_loff,
1642 : : &c_shft, sa_base, flags);
1643 : :
1644 : : /* Move NIX desc to LMT/NIXTX area */
1645 : : cn20k_nix_xmit_mv_lmt_base(laddr, cmd, flags);
1646 : : /* Store sg list directly on lmt line */
1647 : : segdw = cn20k_nix_prepare_mseg(txq, tx_pkts[i], &extm, (uint64_t *)laddr, flags);
1648 : 0 : cn20k_nix_xmit_prepare_tstamp(txq, laddr, tx_pkts[i]->ol_flags, segdw, flags);
1649 [ # # ]: 0 : if (!(flags & NIX_TX_OFFLOAD_SECURITY_F) || !sec) {
1650 : 0 : lnum++;
1651 : : data128 |= (((__uint128_t)(segdw - 1)) << shft);
1652 : : shft += 3;
1653 : : }
1654 : : }
1655 : :
1656 : : if ((flags & NIX_TX_VWQE_F) && !(ws[3] & BIT_ULL(35)))
1657 : : ws[3] = roc_sso_hws_head_wait(ws[0]);
1658 : :
1659 : 0 : left -= burst;
1660 : 0 : tx_pkts += burst;
1661 : :
1662 : : /* Submit CPT instructions if any */
1663 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
1664 : : uint16_t sec_pkts = ((c_lnum << 1) + c_loff);
1665 : :
1666 : : /* Reduce pkts to be sent to CPT */
1667 : : burst -= sec_pkts;
1668 : : if (flags & NIX_TX_VWQE_F)
1669 : : cn20k_nix_vwqe_wait_fc(txq, sec_pkts);
1670 : : cn20k_nix_sec_fc_wait(txq, sec_pkts);
1671 : : cn20k_nix_sec_steorl(c_io_addr, c_lmt_id, c_lnum, c_loff, c_shft);
1672 : : }
1673 : :
1674 : : data0 = (uint64_t)data128;
1675 : : data1 = (uint64_t)(data128 >> 64);
1676 : : /* Make data0 similar to data1 */
1677 : : data0 >>= 16;
1678 : : /* Trigger LMTST */
1679 : : if (burst > 16) {
1680 : : pa0 = io_addr | (data0 & 0x7) << 4;
1681 : : data0 &= ~0x7ULL;
1682 : : /* Move lmtst1..15 sz to bits 63:19 */
1683 : : data0 <<= 16;
1684 : : data0 |= (15ULL << 12);
1685 : : data0 |= (uint64_t)lmt_id;
1686 : :
1687 : : if (flags & NIX_TX_VWQE_F)
1688 : : cn20k_nix_vwqe_wait_fc(txq, 16);
1689 : : /* STEOR0 */
1690 : : roc_lmt_submit_steorl(data0, pa0);
1691 : :
1692 : : pa1 = io_addr | (data1 & 0x7) << 4;
1693 : : data1 &= ~0x7ULL;
1694 : : data1 <<= 16;
1695 : : data1 |= ((uint64_t)(burst - 17)) << 12;
1696 : : data1 |= (uint64_t)(lmt_id + 16);
1697 : :
1698 : : if (flags & NIX_TX_VWQE_F)
1699 : : cn20k_nix_vwqe_wait_fc(txq, burst - 16);
1700 : : /* STEOR1 */
1701 : : roc_lmt_submit_steorl(data1, pa1);
1702 : : } else if (burst) {
1703 : : pa0 = io_addr | (data0 & 0x7) << 4;
1704 : : data0 &= ~0x7ULL;
1705 : : /* Move lmtst1..15 sz to bits 63:19 */
1706 : : data0 <<= 16;
1707 : : data0 |= ((burst - 1ULL) << 12);
1708 : : data0 |= (uint64_t)lmt_id;
1709 : :
1710 : : if (flags & NIX_TX_VWQE_F)
1711 : : cn20k_nix_vwqe_wait_fc(txq, burst);
1712 : : /* STEOR0 */
1713 : : roc_lmt_submit_steorl(data0, pa0);
1714 : : }
1715 : :
1716 : 0 : rte_io_wmb();
1717 [ # # ]: 0 : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && !txq->tx_compl.ena) {
1718 : 0 : cn20k_nix_free_extmbuf(extm);
1719 : : extm = NULL;
1720 : : }
1721 : :
1722 [ # # ]: 0 : if (left)
1723 : 0 : goto again;
1724 : :
1725 : : return pkts;
1726 : : }
1727 : :
1728 : : #if defined(RTE_ARCH_ARM64)
1729 : :
1730 : : static __rte_always_inline void
1731 : : cn20k_nix_prepare_tso(struct rte_mbuf *m, union nix_send_hdr_w1_u *w1, union nix_send_ext_w0_u *w0,
1732 : : uint64_t ol_flags, const uint64_t flags, const uint64_t lso_tun_fmt)
1733 : : {
1734 : : uint16_t lso_sb;
1735 : : uint64_t mask;
1736 : :
1737 : : if (!(ol_flags & RTE_MBUF_F_TX_TCP_SEG))
1738 : : return;
1739 : :
1740 : : mask = -(!w1->il3type);
1741 : : lso_sb = (mask & w1->ol4ptr) + (~mask & w1->il4ptr) + m->l4_len;
1742 : :
1743 : : w0->u |= BIT(14);
1744 : : w0->lso_sb = lso_sb;
1745 : : w0->lso_mps = m->tso_segsz;
1746 : : w0->lso_format = NIX_LSO_FORMAT_IDX_TSOV4 + !!(ol_flags & RTE_MBUF_F_TX_IPV6);
1747 : : w1->ol4type = NIX_SENDL4TYPE_TCP_CKSUM;
1748 : : w1->ol3type = ((!!(ol_flags & RTE_MBUF_F_TX_IPV4)) << 1) +
1749 : : ((!!(ol_flags & RTE_MBUF_F_TX_IPV6)) << 2) +
1750 : : !!(ol_flags & RTE_MBUF_F_TX_IP_CKSUM);
1751 : :
1752 : : /* Handle tunnel tso */
1753 : : if ((flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F) && (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)) {
1754 : : const uint8_t is_udp_tun = (CNXK_NIX_UDP_TUN_BITMASK >>
1755 : : ((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) >> 45)) &
1756 : : 0x1;
1757 : : uint8_t shift = is_udp_tun ? 32 : 0;
1758 : :
1759 : : shift += (!!(ol_flags & RTE_MBUF_F_TX_OUTER_IPV6) << 4);
1760 : : shift += (!!(ol_flags & RTE_MBUF_F_TX_IPV6) << 3);
1761 : :
1762 : : w1->il4type = NIX_SENDL4TYPE_TCP_CKSUM;
1763 : : w1->ol4type = is_udp_tun ? NIX_SENDL4TYPE_UDP_CKSUM : 0;
1764 : : /* Update format for UDP tunneled packet */
1765 : :
1766 : : w0->lso_format = (lso_tun_fmt >> shift);
1767 : : }
1768 : : }
1769 : :
1770 : : static __rte_always_inline uint16_t
1771 : : cn20k_nix_prepare_mseg_vec_noff(struct cn20k_eth_txq *txq, struct rte_mbuf *m,
1772 : : struct rte_mbuf **extm, uint64_t *cmd, uint64x2_t *cmd0,
1773 : : uint64x2_t *cmd1, uint64x2_t *cmd2, uint64x2_t *cmd3,
1774 : : const uint32_t flags)
1775 : : {
1776 : : uint16_t segdw;
1777 : :
1778 : : vst1q_u64(cmd, *cmd0); /* Send hdr */
1779 : : if (flags & NIX_TX_NEED_EXT_HDR) {
1780 : : vst1q_u64(cmd + 2, *cmd2); /* ext hdr */
1781 : : vst1q_u64(cmd + 4, *cmd1); /* sg */
1782 : : } else {
1783 : : vst1q_u64(cmd + 2, *cmd1); /* sg */
1784 : : }
1785 : :
1786 : : segdw = cn20k_nix_prepare_mseg(txq, m, extm, cmd, flags);
1787 : :
1788 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F)
1789 : : vst1q_u64(cmd + segdw * 2 - 2, *cmd3);
1790 : :
1791 : : return segdw;
1792 : : }
1793 : :
1794 : : static __rte_always_inline void
1795 : : cn20k_nix_prepare_mseg_vec_list(struct rte_mbuf *m, uint64_t *cmd, union nix_send_hdr_w0_u *sh,
1796 : : union nix_send_sg_s *sg, const uint32_t flags)
1797 : : {
1798 : : struct rte_mbuf *m_next;
1799 : : uint64_t ol_flags, len;
1800 : : uint64_t *slist, sg_u;
1801 : : uint16_t nb_segs;
1802 : : uint64_t dlen;
1803 : : int i = 1;
1804 : :
1805 : : len = m->pkt_len;
1806 : : ol_flags = m->ol_flags;
1807 : : /* For security we would have already populated the right length */
1808 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F && ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD)
1809 : : len = sh->total;
1810 : : sh->total = len;
1811 : : /* Clear sg->u header before use */
1812 : : sg->u &= 0xFC00000000000000;
1813 : : sg_u = sg->u;
1814 : : slist = &cmd[0];
1815 : :
1816 : : dlen = m->data_len;
1817 : : len -= dlen;
1818 : : sg_u = sg_u | ((uint64_t)dlen);
1819 : :
1820 : : /* Mark mempool object as "put" since it is freed by NIX */
1821 : : RTE_MEMPOOL_CHECK_COOKIES(m->pool, (void **)&m, 1, 0);
1822 : :
1823 : : nb_segs = m->nb_segs - 1;
1824 : : m_next = m->next;
1825 : : m->next = NULL;
1826 : : m->nb_segs = 1;
1827 : : m = m_next;
1828 : : /* Fill mbuf segments */
1829 : : do {
1830 : : m_next = m->next;
1831 : : dlen = m->data_len;
1832 : : len -= dlen;
1833 : : sg_u = sg_u | ((uint64_t)dlen << (i << 4));
1834 : : *slist = rte_mbuf_data_iova(m);
1835 : : slist++;
1836 : : i++;
1837 : : nb_segs--;
1838 : : if (i > 2 && nb_segs) {
1839 : : i = 0;
1840 : : /* Next SG subdesc */
1841 : : *(uint64_t *)slist = sg_u & 0xFC00000000000000;
1842 : : sg->u = sg_u;
1843 : : sg->segs = 3;
1844 : : sg = (union nix_send_sg_s *)slist;
1845 : : sg_u = sg->u;
1846 : : slist++;
1847 : : }
1848 : : m->next = NULL;
1849 : : /* Mark mempool object as "put" since it is freed by NIX */
1850 : : RTE_MEMPOOL_CHECK_COOKIES(m->pool, (void **)&m, 1, 0);
1851 : :
1852 : : m = m_next;
1853 : : } while (nb_segs);
1854 : :
1855 : : /* Add remaining bytes of security data to last seg */
1856 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F && ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD && len) {
1857 : : uint8_t shft = ((i - 1) << 4);
1858 : :
1859 : : dlen = ((sg_u >> shft) & 0xFFFF) + len;
1860 : : sg_u = sg_u & ~(0xFFFFULL << shft);
1861 : : sg_u |= dlen << shft;
1862 : : }
1863 : : sg->u = sg_u;
1864 : : sg->segs = i;
1865 : : }
1866 : :
1867 : : static __rte_always_inline void
1868 : : cn20k_nix_prepare_mseg_vec(struct rte_mbuf *m, uint64_t *cmd, uint64x2_t *cmd0, uint64x2_t *cmd1,
1869 : : const uint8_t segdw, const uint32_t flags)
1870 : : {
1871 : : union nix_send_hdr_w0_u sh;
1872 : : union nix_send_sg_s sg;
1873 : :
1874 : : if (m->nb_segs == 1) {
1875 : : /* Mark mempool object as "put" since it is freed by NIX */
1876 : : RTE_MEMPOOL_CHECK_COOKIES(m->pool, (void **)&m, 1, 0);
1877 : : return;
1878 : : }
1879 : :
1880 : : sh.u = vgetq_lane_u64(cmd0[0], 0);
1881 : : sg.u = vgetq_lane_u64(cmd1[0], 0);
1882 : :
1883 : : cn20k_nix_prepare_mseg_vec_list(m, cmd, &sh, &sg, flags);
1884 : :
1885 : : sh.sizem1 = segdw - 1;
1886 : : cmd0[0] = vsetq_lane_u64(sh.u, cmd0[0], 0);
1887 : : cmd1[0] = vsetq_lane_u64(sg.u, cmd1[0], 0);
1888 : : }
1889 : :
1890 : : #define NIX_DESCS_PER_LOOP 4
1891 : :
1892 : : static __rte_always_inline uint8_t
1893 : : cn20k_nix_prep_lmt_mseg_vector(struct cn20k_eth_txq *txq, struct rte_mbuf **mbufs,
1894 : : struct rte_mbuf **extm, uint64x2_t *cmd0, uint64x2_t *cmd1,
1895 : : uint64x2_t *cmd2, uint64x2_t *cmd3, uint8_t *segdw,
1896 : : uint64_t *lmt_addr, __uint128_t *data128, uint8_t *shift,
1897 : : const uint16_t flags)
1898 : : {
1899 : : uint8_t j, off, lmt_used = 0;
1900 : :
1901 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
1902 : : off = 0;
1903 : : for (j = 0; j < NIX_DESCS_PER_LOOP; j++) {
1904 : : if (off + segdw[j] > 8) {
1905 : : *data128 |= ((__uint128_t)off - 1) << *shift;
1906 : : *shift += 3;
1907 : : lmt_used++;
1908 : : lmt_addr += 16;
1909 : : off = 0;
1910 : : }
1911 : : off += cn20k_nix_prepare_mseg_vec_noff(txq, mbufs[j], extm,
1912 : : lmt_addr + off * 2, &cmd0[j],
1913 : : &cmd1[j], &cmd2[j], &cmd3[j], flags);
1914 : : }
1915 : : *data128 |= ((__uint128_t)off - 1) << *shift;
1916 : : *shift += 3;
1917 : : lmt_used++;
1918 : : return lmt_used;
1919 : : }
1920 : :
1921 : : if (!(flags & NIX_TX_NEED_EXT_HDR) && !(flags & NIX_TX_OFFLOAD_TSTAMP_F)) {
1922 : : /* No segments in 4 consecutive packets. */
1923 : : if ((segdw[0] + segdw[1] + segdw[2] + segdw[3]) <= 8) {
1924 : : vst1q_u64(lmt_addr, cmd0[0]);
1925 : : vst1q_u64(lmt_addr + 2, cmd1[0]);
1926 : : vst1q_u64(lmt_addr + 4, cmd0[1]);
1927 : : vst1q_u64(lmt_addr + 6, cmd1[1]);
1928 : : vst1q_u64(lmt_addr + 8, cmd0[2]);
1929 : : vst1q_u64(lmt_addr + 10, cmd1[2]);
1930 : : vst1q_u64(lmt_addr + 12, cmd0[3]);
1931 : : vst1q_u64(lmt_addr + 14, cmd1[3]);
1932 : :
1933 : : *data128 |= ((__uint128_t)7) << *shift;
1934 : : *shift += 3;
1935 : :
1936 : : /* Mark mempool object as "put" since it is freed by NIX */
1937 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[0]->pool, (void **)&mbufs[0], 1, 0);
1938 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[1]->pool, (void **)&mbufs[1], 1, 0);
1939 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[2]->pool, (void **)&mbufs[2], 1, 0);
1940 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[3]->pool, (void **)&mbufs[3], 1, 0);
1941 : : return 1;
1942 : : }
1943 : : }
1944 : :
1945 : : for (j = 0; j < NIX_DESCS_PER_LOOP;) {
1946 : : /* Fit consecutive packets in same LMTLINE. */
1947 : : if ((segdw[j] + segdw[j + 1]) <= 8) {
1948 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
1949 : : /* TSTAMP takes 4 each, no segs. */
1950 : : vst1q_u64(lmt_addr, cmd0[j]);
1951 : : vst1q_u64(lmt_addr + 2, cmd2[j]);
1952 : : vst1q_u64(lmt_addr + 4, cmd1[j]);
1953 : : vst1q_u64(lmt_addr + 6, cmd3[j]);
1954 : :
1955 : : vst1q_u64(lmt_addr + 8, cmd0[j + 1]);
1956 : : vst1q_u64(lmt_addr + 10, cmd2[j + 1]);
1957 : : vst1q_u64(lmt_addr + 12, cmd1[j + 1]);
1958 : : vst1q_u64(lmt_addr + 14, cmd3[j + 1]);
1959 : :
1960 : : /* Mark mempool object as "put" since it is freed by NIX */
1961 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[j]->pool, (void **)&mbufs[j], 1, 0);
1962 : : RTE_MEMPOOL_CHECK_COOKIES(mbufs[j + 1]->pool,
1963 : : (void **)&mbufs[j + 1], 1, 0);
1964 : : } else if (flags & NIX_TX_NEED_EXT_HDR) {
1965 : : /* EXT header take 3 each, space for 2 segs.*/
1966 : : cn20k_nix_prepare_mseg_vec(mbufs[j], lmt_addr + 6, &cmd0[j],
1967 : : &cmd1[j], segdw[j], flags);
1968 : : vst1q_u64(lmt_addr, cmd0[j]);
1969 : : vst1q_u64(lmt_addr + 2, cmd2[j]);
1970 : : vst1q_u64(lmt_addr + 4, cmd1[j]);
1971 : : off = segdw[j] - 3;
1972 : : off <<= 1;
1973 : : cn20k_nix_prepare_mseg_vec(mbufs[j + 1], lmt_addr + 12 + off,
1974 : : &cmd0[j + 1], &cmd1[j + 1], segdw[j + 1],
1975 : : flags);
1976 : : vst1q_u64(lmt_addr + 6 + off, cmd0[j + 1]);
1977 : : vst1q_u64(lmt_addr + 8 + off, cmd2[j + 1]);
1978 : : vst1q_u64(lmt_addr + 10 + off, cmd1[j + 1]);
1979 : : } else {
1980 : : cn20k_nix_prepare_mseg_vec(mbufs[j], lmt_addr + 4, &cmd0[j],
1981 : : &cmd1[j], segdw[j], flags);
1982 : : vst1q_u64(lmt_addr, cmd0[j]);
1983 : : vst1q_u64(lmt_addr + 2, cmd1[j]);
1984 : : off = segdw[j] - 2;
1985 : : off <<= 1;
1986 : : cn20k_nix_prepare_mseg_vec(mbufs[j + 1], lmt_addr + 8 + off,
1987 : : &cmd0[j + 1], &cmd1[j + 1], segdw[j + 1],
1988 : : flags);
1989 : : vst1q_u64(lmt_addr + 4 + off, cmd0[j + 1]);
1990 : : vst1q_u64(lmt_addr + 6 + off, cmd1[j + 1]);
1991 : : }
1992 : : *data128 |= ((__uint128_t)(segdw[j] + segdw[j + 1]) - 1) << *shift;
1993 : : *shift += 3;
1994 : : j += 2;
1995 : : } else {
1996 : : if ((flags & NIX_TX_NEED_EXT_HDR) && (flags & NIX_TX_OFFLOAD_TSTAMP_F)) {
1997 : : cn20k_nix_prepare_mseg_vec(mbufs[j], lmt_addr + 6, &cmd0[j],
1998 : : &cmd1[j], segdw[j], flags);
1999 : : vst1q_u64(lmt_addr, cmd0[j]);
2000 : : vst1q_u64(lmt_addr + 2, cmd2[j]);
2001 : : vst1q_u64(lmt_addr + 4, cmd1[j]);
2002 : : off = segdw[j] - 4;
2003 : : off <<= 1;
2004 : : vst1q_u64(lmt_addr + 6 + off, cmd3[j]);
2005 : : } else if (flags & NIX_TX_NEED_EXT_HDR) {
2006 : : cn20k_nix_prepare_mseg_vec(mbufs[j], lmt_addr + 6, &cmd0[j],
2007 : : &cmd1[j], segdw[j], flags);
2008 : : vst1q_u64(lmt_addr, cmd0[j]);
2009 : : vst1q_u64(lmt_addr + 2, cmd2[j]);
2010 : : vst1q_u64(lmt_addr + 4, cmd1[j]);
2011 : : } else {
2012 : : cn20k_nix_prepare_mseg_vec(mbufs[j], lmt_addr + 4, &cmd0[j],
2013 : : &cmd1[j], segdw[j], flags);
2014 : : vst1q_u64(lmt_addr, cmd0[j]);
2015 : : vst1q_u64(lmt_addr + 2, cmd1[j]);
2016 : : }
2017 : : *data128 |= ((__uint128_t)(segdw[j]) - 1) << *shift;
2018 : : *shift += 3;
2019 : : j++;
2020 : : }
2021 : : lmt_used++;
2022 : : lmt_addr += 16;
2023 : : }
2024 : :
2025 : : return lmt_used;
2026 : : }
2027 : :
2028 : : static __rte_always_inline void
2029 : : cn20k_nix_lmt_next(uint8_t dw, uintptr_t laddr, uint8_t *lnum, uint8_t *loff, uint8_t *shift,
2030 : : __uint128_t *data128, uintptr_t *next)
2031 : : {
2032 : : /* Go to next line if we are out of space */
2033 : : if ((*loff + (dw << 4)) > 128) {
2034 : : *data128 = *data128 | (((__uint128_t)((*loff >> 4) - 1)) << *shift);
2035 : : *shift = *shift + 3;
2036 : : *loff = 0;
2037 : : *lnum = *lnum + 1;
2038 : : }
2039 : :
2040 : : *next = (uintptr_t)LMT_OFF(laddr, *lnum, *loff);
2041 : : *loff = *loff + (dw << 4);
2042 : : }
2043 : :
2044 : : static __rte_always_inline void
2045 : : cn20k_nix_xmit_store(struct cn20k_eth_txq *txq, struct rte_mbuf *mbuf, struct rte_mbuf **extm,
2046 : : uint8_t segdw, uintptr_t laddr, uint64x2_t cmd0, uint64x2_t cmd1,
2047 : : uint64x2_t cmd2, uint64x2_t cmd3, const uint16_t flags)
2048 : : {
2049 : : uint8_t off;
2050 : :
2051 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) {
2052 : : cn20k_nix_prepare_mseg_vec_noff(txq, mbuf, extm, LMT_OFF(laddr, 0, 0), &cmd0, &cmd1,
2053 : : &cmd2, &cmd3, flags);
2054 : : return;
2055 : : }
2056 : : if (flags & NIX_TX_MULTI_SEG_F) {
2057 : : if ((flags & NIX_TX_NEED_EXT_HDR) && (flags & NIX_TX_OFFLOAD_TSTAMP_F)) {
2058 : : cn20k_nix_prepare_mseg_vec(mbuf, LMT_OFF(laddr, 0, 48), &cmd0, &cmd1, segdw,
2059 : : flags);
2060 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2061 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd2);
2062 : : vst1q_u64(LMT_OFF(laddr, 0, 32), cmd1);
2063 : : off = segdw - 4;
2064 : : off <<= 4;
2065 : : vst1q_u64(LMT_OFF(laddr, 0, 48 + off), cmd3);
2066 : : } else if (flags & NIX_TX_NEED_EXT_HDR) {
2067 : : cn20k_nix_prepare_mseg_vec(mbuf, LMT_OFF(laddr, 0, 48), &cmd0, &cmd1, segdw,
2068 : : flags);
2069 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2070 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd2);
2071 : : vst1q_u64(LMT_OFF(laddr, 0, 32), cmd1);
2072 : : } else {
2073 : : cn20k_nix_prepare_mseg_vec(mbuf, LMT_OFF(laddr, 0, 32), &cmd0, &cmd1, segdw,
2074 : : flags);
2075 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2076 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd1);
2077 : : }
2078 : : } else if (flags & NIX_TX_NEED_EXT_HDR) {
2079 : : /* Store the prepared send desc to LMT lines */
2080 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
2081 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2082 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd2);
2083 : : vst1q_u64(LMT_OFF(laddr, 0, 32), cmd1);
2084 : : vst1q_u64(LMT_OFF(laddr, 0, 48), cmd3);
2085 : : } else {
2086 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2087 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd2);
2088 : : vst1q_u64(LMT_OFF(laddr, 0, 32), cmd1);
2089 : : }
2090 : : RTE_MEMPOOL_CHECK_COOKIES(mbuf->pool, (void **)&mbuf, 1, 0);
2091 : : } else {
2092 : : /* Store the prepared send desc to LMT lines */
2093 : : vst1q_u64(LMT_OFF(laddr, 0, 0), cmd0);
2094 : : vst1q_u64(LMT_OFF(laddr, 0, 16), cmd1);
2095 : : RTE_MEMPOOL_CHECK_COOKIES(mbuf->pool, (void **)&mbuf, 1, 0);
2096 : : }
2097 : : }
2098 : :
2099 : : static __rte_always_inline uint16_t
2100 : : cn20k_nix_xmit_pkts_vector(void *tx_queue, uint64_t *ws, struct rte_mbuf **tx_pkts, uint16_t pkts,
2101 : : uint64_t *cmd, const uint16_t flags)
2102 : : {
2103 : : uint64x2_t dataoff_iova0, dataoff_iova1, dataoff_iova2, dataoff_iova3;
2104 : : uint64x2_t len_olflags0, len_olflags1, len_olflags2, len_olflags3;
2105 : : uint64x2_t cmd0[NIX_DESCS_PER_LOOP], cmd1[NIX_DESCS_PER_LOOP], cmd2[NIX_DESCS_PER_LOOP],
2106 : : cmd3[NIX_DESCS_PER_LOOP];
2107 : : uint16_t left, scalar, burst, i, lmt_id, c_lmt_id;
2108 : : uint64_t *mbuf0, *mbuf1, *mbuf2, *mbuf3, pa;
2109 : : uint64x2_t senddesc01_w0, senddesc23_w0;
2110 : : uint64x2_t senddesc01_w1, senddesc23_w1;
2111 : : uint64x2_t sendext01_w0, sendext23_w0;
2112 : : uint64x2_t sendext01_w1, sendext23_w1;
2113 : : uint64x2_t sendmem01_w0, sendmem23_w0;
2114 : : uint64x2_t sendmem01_w1, sendmem23_w1;
2115 : : uint8_t segdw[NIX_DESCS_PER_LOOP + 1];
2116 : : uint64x2_t sgdesc01_w0, sgdesc23_w0;
2117 : : uint64x2_t sgdesc01_w1, sgdesc23_w1;
2118 : : struct cn20k_eth_txq *txq = tx_queue;
2119 : : rte_iova_t io_addr = txq->io_addr;
2120 : : uint8_t lnum, shift = 0, loff = 0;
2121 : : uintptr_t laddr = txq->lmt_base;
2122 : : uint8_t c_lnum, c_shft, c_loff;
2123 : : uint64x2_t ltypes01, ltypes23;
2124 : : uint64x2_t xtmp128, ytmp128;
2125 : : uint64x2_t xmask01, xmask23;
2126 : : uintptr_t c_laddr = laddr;
2127 : : rte_iova_t c_io_addr;
2128 : : uint64_t sa_base;
2129 : : union wdata {
2130 : : __uint128_t data128;
2131 : : uint64_t data[2];
2132 : : } wd;
2133 : : struct rte_mbuf *extm = NULL;
2134 : :
2135 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && txq->tx_compl.ena)
2136 : : handle_tx_completion_pkts(txq, flags & NIX_TX_VWQE_F);
2137 : :
2138 : : if (!(flags & NIX_TX_VWQE_F)) {
2139 : : scalar = pkts & (NIX_DESCS_PER_LOOP - 1);
2140 : : pkts = RTE_ALIGN_FLOOR(pkts, NIX_DESCS_PER_LOOP);
2141 : : NIX_XMIT_FC_CHECK_RETURN(txq, pkts);
2142 : : } else {
2143 : : scalar = pkts & (NIX_DESCS_PER_LOOP - 1);
2144 : : pkts = RTE_ALIGN_FLOOR(pkts, NIX_DESCS_PER_LOOP);
2145 : : }
2146 : :
2147 : : /* Perform header writes before barrier for TSO */
2148 : : if (flags & NIX_TX_OFFLOAD_TSO_F) {
2149 : : for (i = 0; i < pkts; i++)
2150 : : cn20k_nix_xmit_prepare_tso(tx_pkts[i], flags);
2151 : : }
2152 : :
2153 : : if (!(flags & NIX_TX_VWQE_F)) {
2154 : : senddesc01_w0 = vld1q_dup_u64(&txq->send_hdr_w0);
2155 : : } else {
2156 : : uint64_t w0 = (txq->send_hdr_w0 & 0xFFFFF00000000000) |
2157 : : ((uint64_t)(cn20k_nix_tx_ext_subs(flags) + 1) << 40);
2158 : :
2159 : : senddesc01_w0 = vdupq_n_u64(w0);
2160 : : }
2161 : : senddesc23_w0 = senddesc01_w0;
2162 : :
2163 : : senddesc01_w1 = vdupq_n_u64(0);
2164 : : senddesc23_w1 = senddesc01_w1;
2165 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
2166 : : sgdesc01_w0 = vdupq_n_u64((NIX_SUBDC_SG << 60) | (NIX_SENDLDTYPE_LDWB << 58) |
2167 : : BIT_ULL(48));
2168 : : else
2169 : : sgdesc01_w0 = vdupq_n_u64((NIX_SUBDC_SG << 60) | BIT_ULL(48));
2170 : : sgdesc23_w0 = sgdesc01_w0;
2171 : :
2172 : : if (flags & NIX_TX_NEED_EXT_HDR) {
2173 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
2174 : : sendext01_w0 = vdupq_n_u64((NIX_SUBDC_EXT << 60) | BIT_ULL(15));
2175 : : sendmem01_w0 = vdupq_n_u64((NIX_SUBDC_MEM << 60) |
2176 : : (NIX_SENDMEMALG_SETTSTMP << 56));
2177 : : sendmem23_w0 = sendmem01_w0;
2178 : : sendmem01_w1 = vdupq_n_u64(txq->ts_mem);
2179 : : sendmem23_w1 = sendmem01_w1;
2180 : : } else {
2181 : : sendext01_w0 = vdupq_n_u64((NIX_SUBDC_EXT << 60));
2182 : : }
2183 : : sendext23_w0 = sendext01_w0;
2184 : :
2185 : : if (flags & NIX_TX_OFFLOAD_VLAN_QINQ_F)
2186 : : sendext01_w1 = vdupq_n_u64(12 | 12U << 24);
2187 : : else
2188 : : sendext01_w1 = vdupq_n_u64(0);
2189 : : sendext23_w1 = sendext01_w1;
2190 : : }
2191 : :
2192 : : /* Get LMT base address and LMT ID as lcore id */
2193 : : ROC_LMT_BASE_ID_GET(laddr, lmt_id);
2194 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
2195 : : ROC_LMT_CPT_BASE_ID_GET(c_laddr, c_lmt_id);
2196 : : c_io_addr = txq->cpt_io_addr;
2197 : : sa_base = txq->sa_base;
2198 : : }
2199 : :
2200 : : left = pkts;
2201 : : again:
2202 : : /* Number of packets to prepare depends on offloads enabled. */
2203 : : burst = left > cn20k_nix_pkts_per_vec_brst(flags) ? cn20k_nix_pkts_per_vec_brst(flags) :
2204 : : left;
2205 : : if (flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F)) {
2206 : : wd.data128 = 0;
2207 : : shift = 16;
2208 : : }
2209 : : lnum = 0;
2210 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
2211 : : loff = 0;
2212 : : c_loff = 0;
2213 : : c_lnum = 0;
2214 : : c_shft = 16;
2215 : : }
2216 : :
2217 : : for (i = 0; i < burst; i += NIX_DESCS_PER_LOOP) {
2218 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F &&
2219 : : (((int)((16 - c_lnum) << 1) - c_loff) < 4)) {
2220 : : burst = i;
2221 : : break;
2222 : : }
2223 : :
2224 : : if (flags & NIX_TX_MULTI_SEG_F) {
2225 : : uint8_t j;
2226 : :
2227 : : for (j = 0; j < NIX_DESCS_PER_LOOP; j++) {
2228 : : struct rte_mbuf *m = tx_pkts[j];
2229 : :
2230 : : cn20k_nix_tx_mbuf_validate(m, flags);
2231 : :
2232 : : /* Get dwords based on nb_segs. */
2233 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F &&
2234 : : flags & NIX_TX_MULTI_SEG_F))
2235 : : segdw[j] = NIX_NB_SEGS_TO_SEGDW(m->nb_segs);
2236 : : else
2237 : : segdw[j] = cn20k_nix_mbuf_sg_dwords(m);
2238 : :
2239 : : /* Add dwords based on offloads. */
2240 : : segdw[j] += 1 + /* SEND HDR */
2241 : : !!(flags & NIX_TX_NEED_EXT_HDR) +
2242 : : !!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
2243 : : }
2244 : :
2245 : : /* Check if there are enough LMTLINES for this loop.
2246 : : * Consider previous line to be partial.
2247 : : */
2248 : : if (lnum + 4 >= 32) {
2249 : : uint8_t ldwords_con = 0, lneeded = 0;
2250 : :
2251 : : if ((loff >> 4) + segdw[0] > 8) {
2252 : : lneeded += 1;
2253 : : ldwords_con = segdw[0];
2254 : : } else {
2255 : : ldwords_con = (loff >> 4) + segdw[0];
2256 : : }
2257 : :
2258 : : for (j = 1; j < NIX_DESCS_PER_LOOP; j++) {
2259 : : ldwords_con += segdw[j];
2260 : : if (ldwords_con > 8) {
2261 : : lneeded += 1;
2262 : : ldwords_con = segdw[j];
2263 : : }
2264 : : }
2265 : : lneeded += 1;
2266 : : if (lnum + lneeded > 32) {
2267 : : burst = i;
2268 : : break;
2269 : : }
2270 : : }
2271 : : }
2272 : : /* Clear lower 32bit of SEND_HDR_W0 and SEND_SG_W0 */
2273 : : senddesc01_w0 = vbicq_u64(senddesc01_w0, vdupq_n_u64(0x800FFFFFFFF));
2274 : : sgdesc01_w0 = vbicq_u64(sgdesc01_w0, vdupq_n_u64(0xFFFFFFFF));
2275 : :
2276 : : senddesc23_w0 = senddesc01_w0;
2277 : : sgdesc23_w0 = sgdesc01_w0;
2278 : :
2279 : : /* Clear vlan enables. */
2280 : : if (flags & NIX_TX_NEED_EXT_HDR) {
2281 : : sendext01_w1 = vbicq_u64(sendext01_w1, vdupq_n_u64(0x3FFFF00FFFF00));
2282 : : sendext23_w1 = sendext01_w1;
2283 : : }
2284 : :
2285 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
2286 : : /* Reset send mem alg to SETTSTMP from SUB*/
2287 : : sendmem01_w0 = vbicq_u64(sendmem01_w0, vdupq_n_u64(BIT_ULL(59)));
2288 : : /* Reset send mem address to default. */
2289 : : sendmem01_w1 = vbicq_u64(sendmem01_w1, vdupq_n_u64(0xF));
2290 : : sendmem23_w0 = sendmem01_w0;
2291 : : sendmem23_w1 = sendmem01_w1;
2292 : : }
2293 : :
2294 : : if (flags & NIX_TX_OFFLOAD_TSO_F) {
2295 : : /* Clear the LSO enable bit. */
2296 : : sendext01_w0 = vbicq_u64(sendext01_w0, vdupq_n_u64(BIT_ULL(14)));
2297 : : sendext23_w0 = sendext01_w0;
2298 : : }
2299 : :
2300 : : /* Move mbufs to iova */
2301 : : mbuf0 = (uint64_t *)tx_pkts[0];
2302 : : mbuf1 = (uint64_t *)tx_pkts[1];
2303 : : mbuf2 = (uint64_t *)tx_pkts[2];
2304 : : mbuf3 = (uint64_t *)tx_pkts[3];
2305 : :
2306 : : /*
2307 : : * Get mbuf's, olflags, iova, pktlen, dataoff
2308 : : * dataoff_iovaX.D[0] = iova,
2309 : : * dataoff_iovaX.D[1](15:0) = mbuf->dataoff
2310 : : * len_olflagsX.D[0] = ol_flags,
2311 : : * len_olflagsX.D[1](63:32) = mbuf->pkt_len
2312 : : */
2313 : : dataoff_iova0 =
2314 : : vsetq_lane_u64(((struct rte_mbuf *)mbuf0)->data_off, vld1q_u64(mbuf0), 1);
2315 : : len_olflags0 = vld1q_u64(mbuf0 + 3);
2316 : : dataoff_iova1 =
2317 : : vsetq_lane_u64(((struct rte_mbuf *)mbuf1)->data_off, vld1q_u64(mbuf1), 1);
2318 : : len_olflags1 = vld1q_u64(mbuf1 + 3);
2319 : : dataoff_iova2 =
2320 : : vsetq_lane_u64(((struct rte_mbuf *)mbuf2)->data_off, vld1q_u64(mbuf2), 1);
2321 : : len_olflags2 = vld1q_u64(mbuf2 + 3);
2322 : : dataoff_iova3 =
2323 : : vsetq_lane_u64(((struct rte_mbuf *)mbuf3)->data_off, vld1q_u64(mbuf3), 1);
2324 : : len_olflags3 = vld1q_u64(mbuf3 + 3);
2325 : :
2326 : : /* Move mbufs to point pool */
2327 : : mbuf0 = (uint64_t *)((uintptr_t)mbuf0 + offsetof(struct rte_mbuf, pool));
2328 : : mbuf1 = (uint64_t *)((uintptr_t)mbuf1 + offsetof(struct rte_mbuf, pool));
2329 : : mbuf2 = (uint64_t *)((uintptr_t)mbuf2 + offsetof(struct rte_mbuf, pool));
2330 : : mbuf3 = (uint64_t *)((uintptr_t)mbuf3 + offsetof(struct rte_mbuf, pool));
2331 : :
2332 : : if (flags & (NIX_TX_OFFLOAD_OL3_OL4_CSUM_F | NIX_TX_OFFLOAD_L3_L4_CSUM_F)) {
2333 : : /* Get tx_offload for ol2, ol3, l2, l3 lengths */
2334 : : /*
2335 : : * E(8):OL2_LEN(7):OL3_LEN(9):E(24):L3_LEN(9):L2_LEN(7)
2336 : : * E(8):OL2_LEN(7):OL3_LEN(9):E(24):L3_LEN(9):L2_LEN(7)
2337 : : */
2338 : :
2339 : : asm volatile("LD1 {%[a].D}[0],[%[in]]\n\t"
2340 : : : [a] "+w"(senddesc01_w1)
2341 : : : [in] "r"(mbuf0 + 2)
2342 : : : "memory");
2343 : :
2344 : : asm volatile("LD1 {%[a].D}[1],[%[in]]\n\t"
2345 : : : [a] "+w"(senddesc01_w1)
2346 : : : [in] "r"(mbuf1 + 2)
2347 : : : "memory");
2348 : :
2349 : : asm volatile("LD1 {%[b].D}[0],[%[in]]\n\t"
2350 : : : [b] "+w"(senddesc23_w1)
2351 : : : [in] "r"(mbuf2 + 2)
2352 : : : "memory");
2353 : :
2354 : : asm volatile("LD1 {%[b].D}[1],[%[in]]\n\t"
2355 : : : [b] "+w"(senddesc23_w1)
2356 : : : [in] "r"(mbuf3 + 2)
2357 : : : "memory");
2358 : :
2359 : : /* Get pool pointer alone */
2360 : : mbuf0 = (uint64_t *)*mbuf0;
2361 : : mbuf1 = (uint64_t *)*mbuf1;
2362 : : mbuf2 = (uint64_t *)*mbuf2;
2363 : : mbuf3 = (uint64_t *)*mbuf3;
2364 : : } else {
2365 : : /* Get pool pointer alone */
2366 : : mbuf0 = (uint64_t *)*mbuf0;
2367 : : mbuf1 = (uint64_t *)*mbuf1;
2368 : : mbuf2 = (uint64_t *)*mbuf2;
2369 : : mbuf3 = (uint64_t *)*mbuf3;
2370 : : }
2371 : :
2372 : : const uint8x16_t shuf_mask2 = {
2373 : : 0x4, 0x5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2374 : : 0xc, 0xd, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2375 : : };
2376 : : xtmp128 = vzip2q_u64(len_olflags0, len_olflags1);
2377 : : ytmp128 = vzip2q_u64(len_olflags2, len_olflags3);
2378 : :
2379 : : /*
2380 : : * Pick only 16 bits of pktlen preset at bits 63:32
2381 : : * and place them at bits 15:0.
2382 : : */
2383 : : xtmp128 = vqtbl1q_u8(xtmp128, shuf_mask2);
2384 : : ytmp128 = vqtbl1q_u8(ytmp128, shuf_mask2);
2385 : :
2386 : : /* Add pairwise to get dataoff + iova in sgdesc_w1 */
2387 : : sgdesc01_w1 = vpaddq_u64(dataoff_iova0, dataoff_iova1);
2388 : : sgdesc23_w1 = vpaddq_u64(dataoff_iova2, dataoff_iova3);
2389 : :
2390 : : /* Orr both sgdesc_w0 and senddesc_w0 with 16 bits of
2391 : : * pktlen at 15:0 position.
2392 : : */
2393 : : sgdesc01_w0 = vorrq_u64(sgdesc01_w0, xtmp128);
2394 : : sgdesc23_w0 = vorrq_u64(sgdesc23_w0, ytmp128);
2395 : : senddesc01_w0 = vorrq_u64(senddesc01_w0, xtmp128);
2396 : : senddesc23_w0 = vorrq_u64(senddesc23_w0, ytmp128);
2397 : :
2398 : : /* Move mbuf to point to pool_id. */
2399 : : mbuf0 = (uint64_t *)((uintptr_t)mbuf0 + offsetof(struct rte_mempool, pool_id));
2400 : : mbuf1 = (uint64_t *)((uintptr_t)mbuf1 + offsetof(struct rte_mempool, pool_id));
2401 : : mbuf2 = (uint64_t *)((uintptr_t)mbuf2 + offsetof(struct rte_mempool, pool_id));
2402 : : mbuf3 = (uint64_t *)((uintptr_t)mbuf3 + offsetof(struct rte_mempool, pool_id));
2403 : :
2404 : : if ((flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
2405 : : !(flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
2406 : : /*
2407 : : * Lookup table to translate ol_flags to
2408 : : * il3/il4 types. But we still use ol3/ol4 types in
2409 : : * senddesc_w1 as only one header processing is enabled.
2410 : : */
2411 : : const uint8x16_t tbl = {
2412 : : /* [0-15] = il4type:il3type */
2413 : : 0x00, /* none */
2414 : : 0x14, /* RTE_MBUF_F_TX_TCP_CKSUM (IPv6 assumed) */
2415 : : 0x24, /* RTE_MBUF_F_TX_SCTP_CKSUM (IPv6 assumed) */
2416 : : 0x34, /* RTE_MBUF_F_TX_UDP_CKSUM (IPv6 assumed) */
2417 : : 0x03, /* RTE_MBUF_F_TX_IP_CKSUM */
2418 : : 0x13, /* RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_TCP_CKSUM */
2419 : : 0x23, /* RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_SCTP_CKSUM */
2420 : : 0x33, /* RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_CKSUM */
2421 : : 0x02, /* RTE_MBUF_F_TX_IPV4 */
2422 : : 0x12, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_TCP_CKSUM */
2423 : : 0x22, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_SCTP_CKSUM */
2424 : : 0x32, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_UDP_CKSUM */
2425 : : 0x03, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM */
2426 : : 0x13, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2427 : : * RTE_MBUF_F_TX_TCP_CKSUM
2428 : : */
2429 : : 0x23, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2430 : : * RTE_MBUF_F_TX_SCTP_CKSUM
2431 : : */
2432 : : 0x33, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2433 : : * RTE_MBUF_F_TX_UDP_CKSUM
2434 : : */
2435 : : };
2436 : :
2437 : : /* Extract olflags to translate to iltypes */
2438 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2439 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2440 : :
2441 : : /*
2442 : : * E(47):L3_LEN(9):L2_LEN(7+z)
2443 : : * E(47):L3_LEN(9):L2_LEN(7+z)
2444 : : */
2445 : : senddesc01_w1 = vshlq_n_u64(senddesc01_w1, 1);
2446 : : senddesc23_w1 = vshlq_n_u64(senddesc23_w1, 1);
2447 : :
2448 : : /* Move OLFLAGS bits 55:52 to 51:48
2449 : : * with zeros prepended on the byte and rest
2450 : : * don't care
2451 : : */
2452 : : xtmp128 = vshrq_n_u8(xtmp128, 4);
2453 : : ytmp128 = vshrq_n_u8(ytmp128, 4);
2454 : : /*
2455 : : * E(48):L3_LEN(8):L2_LEN(z+7)
2456 : : * E(48):L3_LEN(8):L2_LEN(z+7)
2457 : : */
2458 : : const int8x16_t tshft3 = {
2459 : : -1, 0, 8, 8, 8, 8, 8, 8,
2460 : : -1, 0, 8, 8, 8, 8, 8, 8,
2461 : : };
2462 : :
2463 : : senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
2464 : : senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
2465 : :
2466 : : /* Do the lookup */
2467 : : ltypes01 = vqtbl1q_u8(tbl, xtmp128);
2468 : : ltypes23 = vqtbl1q_u8(tbl, ytmp128);
2469 : :
2470 : : /* Pick only relevant fields i.e Bit 48:55 of iltype
2471 : : * and place it in ol3/ol4type of senddesc_w1
2472 : : */
2473 : : const uint8x16_t shuf_mask0 = {
2474 : : 0xFF, 0xFF, 0xFF, 0xFF, 0x6, 0xFF, 0xFF, 0xFF,
2475 : : 0xFF, 0xFF, 0xFF, 0xFF, 0xE, 0xFF, 0xFF, 0xFF,
2476 : : };
2477 : :
2478 : : ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
2479 : : ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
2480 : :
2481 : : /* Prepare ol4ptr, ol3ptr from ol3len, ol2len.
2482 : : * a [E(32):E(16):OL3(8):OL2(8)]
2483 : : * a = a + (a << 8)
2484 : : * a [E(32):E(16):(OL3+OL2):OL2]
2485 : : * => E(32):E(16)::OL4PTR(8):OL3PTR(8)
2486 : : */
2487 : : senddesc01_w1 = vaddq_u8(senddesc01_w1, vshlq_n_u16(senddesc01_w1, 8));
2488 : : senddesc23_w1 = vaddq_u8(senddesc23_w1, vshlq_n_u16(senddesc23_w1, 8));
2489 : :
2490 : : /* Move ltypes to senddesc*_w1 */
2491 : : senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
2492 : : senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
2493 : : } else if (!(flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
2494 : : (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
2495 : : /*
2496 : : * Lookup table to translate ol_flags to
2497 : : * ol3/ol4 types.
2498 : : */
2499 : :
2500 : : const uint8x16_t tbl = {
2501 : : /* [0-15] = ol4type:ol3type */
2502 : : 0x00, /* none */
2503 : : 0x03, /* OUTER_IP_CKSUM */
2504 : : 0x02, /* OUTER_IPV4 */
2505 : : 0x03, /* OUTER_IPV4 | OUTER_IP_CKSUM */
2506 : : 0x04, /* OUTER_IPV6 */
2507 : : 0x00, /* OUTER_IPV6 | OUTER_IP_CKSUM */
2508 : : 0x00, /* OUTER_IPV6 | OUTER_IPV4 */
2509 : : 0x00, /* OUTER_IPV6 | OUTER_IPV4 |
2510 : : * OUTER_IP_CKSUM
2511 : : */
2512 : : 0x00, /* OUTER_UDP_CKSUM */
2513 : : 0x33, /* OUTER_UDP_CKSUM | OUTER_IP_CKSUM */
2514 : : 0x32, /* OUTER_UDP_CKSUM | OUTER_IPV4 */
2515 : : 0x33, /* OUTER_UDP_CKSUM | OUTER_IPV4 |
2516 : : * OUTER_IP_CKSUM
2517 : : */
2518 : : 0x34, /* OUTER_UDP_CKSUM | OUTER_IPV6 */
2519 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2520 : : * OUTER_IP_CKSUM
2521 : : */
2522 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2523 : : * OUTER_IPV4
2524 : : */
2525 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2526 : : * OUTER_IPV4 | OUTER_IP_CKSUM
2527 : : */
2528 : : };
2529 : :
2530 : : /* Extract olflags to translate to iltypes */
2531 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2532 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2533 : :
2534 : : /*
2535 : : * E(47):OL3_LEN(9):OL2_LEN(7+z)
2536 : : * E(47):OL3_LEN(9):OL2_LEN(7+z)
2537 : : */
2538 : : const uint8x16_t shuf_mask5 = {
2539 : : 0x6, 0x5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2540 : : 0xE, 0xD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2541 : : };
2542 : : senddesc01_w1 = vqtbl1q_u8(senddesc01_w1, shuf_mask5);
2543 : : senddesc23_w1 = vqtbl1q_u8(senddesc23_w1, shuf_mask5);
2544 : :
2545 : : /* Extract outer ol flags only */
2546 : : const uint64x2_t o_cksum_mask = {
2547 : : 0x1C00020000000000,
2548 : : 0x1C00020000000000,
2549 : : };
2550 : :
2551 : : xtmp128 = vandq_u64(xtmp128, o_cksum_mask);
2552 : : ytmp128 = vandq_u64(ytmp128, o_cksum_mask);
2553 : :
2554 : : /* Extract OUTER_UDP_CKSUM bit 41 and
2555 : : * move it to bit 61
2556 : : */
2557 : :
2558 : : xtmp128 = xtmp128 | vshlq_n_u64(xtmp128, 20);
2559 : : ytmp128 = ytmp128 | vshlq_n_u64(ytmp128, 20);
2560 : :
2561 : : /* Shift oltype by 2 to start nibble from BIT(56)
2562 : : * instead of BIT(58)
2563 : : */
2564 : : xtmp128 = vshrq_n_u8(xtmp128, 2);
2565 : : ytmp128 = vshrq_n_u8(ytmp128, 2);
2566 : : /*
2567 : : * E(48):L3_LEN(8):L2_LEN(z+7)
2568 : : * E(48):L3_LEN(8):L2_LEN(z+7)
2569 : : */
2570 : : const int8x16_t tshft3 = {
2571 : : -1, 0, 8, 8, 8, 8, 8, 8,
2572 : : -1, 0, 8, 8, 8, 8, 8, 8,
2573 : : };
2574 : :
2575 : : senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
2576 : : senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
2577 : :
2578 : : /* Do the lookup */
2579 : : ltypes01 = vqtbl1q_u8(tbl, xtmp128);
2580 : : ltypes23 = vqtbl1q_u8(tbl, ytmp128);
2581 : :
2582 : : /* Pick only relevant fields i.e Bit 56:63 of oltype
2583 : : * and place it in ol3/ol4type of senddesc_w1
2584 : : */
2585 : : const uint8x16_t shuf_mask0 = {
2586 : : 0xFF, 0xFF, 0xFF, 0xFF, 0x7, 0xFF, 0xFF, 0xFF,
2587 : : 0xFF, 0xFF, 0xFF, 0xFF, 0xF, 0xFF, 0xFF, 0xFF,
2588 : : };
2589 : :
2590 : : ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
2591 : : ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
2592 : :
2593 : : /* Prepare ol4ptr, ol3ptr from ol3len, ol2len.
2594 : : * a [E(32):E(16):OL3(8):OL2(8)]
2595 : : * a = a + (a << 8)
2596 : : * a [E(32):E(16):(OL3+OL2):OL2]
2597 : : * => E(32):E(16)::OL4PTR(8):OL3PTR(8)
2598 : : */
2599 : : senddesc01_w1 = vaddq_u8(senddesc01_w1, vshlq_n_u16(senddesc01_w1, 8));
2600 : : senddesc23_w1 = vaddq_u8(senddesc23_w1, vshlq_n_u16(senddesc23_w1, 8));
2601 : :
2602 : : /* Move ltypes to senddesc*_w1 */
2603 : : senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
2604 : : senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
2605 : : } else if ((flags & NIX_TX_OFFLOAD_L3_L4_CSUM_F) &&
2606 : : (flags & NIX_TX_OFFLOAD_OL3_OL4_CSUM_F)) {
2607 : : /* Lookup table to translate ol_flags to
2608 : : * ol4type, ol3type, il4type, il3type of senddesc_w1
2609 : : */
2610 : : const uint8x16x2_t tbl = {{
2611 : : {
2612 : : /* [0-15] = il4type:il3type */
2613 : : 0x00, /* none */
2614 : : 0x14, /* RTE_MBUF_F_TX_TCP_CKSUM (IPv6) */
2615 : : 0x24, /* RTE_MBUF_F_TX_SCTP_CKSUM (IPv6) */
2616 : : 0x34, /* RTE_MBUF_F_TX_UDP_CKSUM (IPv6) */
2617 : : 0x03, /* RTE_MBUF_F_TX_IP_CKSUM */
2618 : : 0x13, /* RTE_MBUF_F_TX_IP_CKSUM |
2619 : : * RTE_MBUF_F_TX_TCP_CKSUM
2620 : : */
2621 : : 0x23, /* RTE_MBUF_F_TX_IP_CKSUM |
2622 : : * RTE_MBUF_F_TX_SCTP_CKSUM
2623 : : */
2624 : : 0x33, /* RTE_MBUF_F_TX_IP_CKSUM |
2625 : : * RTE_MBUF_F_TX_UDP_CKSUM
2626 : : */
2627 : : 0x02, /* RTE_MBUF_F_TX_IPV4 */
2628 : : 0x12, /* RTE_MBUF_F_TX_IPV4 |
2629 : : * RTE_MBUF_F_TX_TCP_CKSUM
2630 : : */
2631 : : 0x22, /* RTE_MBUF_F_TX_IPV4 |
2632 : : * RTE_MBUF_F_TX_SCTP_CKSUM
2633 : : */
2634 : : 0x32, /* RTE_MBUF_F_TX_IPV4 |
2635 : : * RTE_MBUF_F_TX_UDP_CKSUM
2636 : : */
2637 : : 0x03, /* RTE_MBUF_F_TX_IPV4 |
2638 : : * RTE_MBUF_F_TX_IP_CKSUM
2639 : : */
2640 : : 0x13, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2641 : : * RTE_MBUF_F_TX_TCP_CKSUM
2642 : : */
2643 : : 0x23, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2644 : : * RTE_MBUF_F_TX_SCTP_CKSUM
2645 : : */
2646 : : 0x33, /* RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM |
2647 : : * RTE_MBUF_F_TX_UDP_CKSUM
2648 : : */
2649 : : },
2650 : :
2651 : : {
2652 : : /* [16-31] = ol4type:ol3type */
2653 : : 0x00, /* none */
2654 : : 0x03, /* OUTER_IP_CKSUM */
2655 : : 0x02, /* OUTER_IPV4 */
2656 : : 0x03, /* OUTER_IPV4 | OUTER_IP_CKSUM */
2657 : : 0x04, /* OUTER_IPV6 */
2658 : : 0x00, /* OUTER_IPV6 | OUTER_IP_CKSUM */
2659 : : 0x00, /* OUTER_IPV6 | OUTER_IPV4 */
2660 : : 0x00, /* OUTER_IPV6 | OUTER_IPV4 |
2661 : : * OUTER_IP_CKSUM
2662 : : */
2663 : : 0x00, /* OUTER_UDP_CKSUM */
2664 : : 0x33, /* OUTER_UDP_CKSUM |
2665 : : * OUTER_IP_CKSUM
2666 : : */
2667 : : 0x32, /* OUTER_UDP_CKSUM |
2668 : : * OUTER_IPV4
2669 : : */
2670 : : 0x33, /* OUTER_UDP_CKSUM |
2671 : : * OUTER_IPV4 | OUTER_IP_CKSUM
2672 : : */
2673 : : 0x34, /* OUTER_UDP_CKSUM |
2674 : : * OUTER_IPV6
2675 : : */
2676 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2677 : : * OUTER_IP_CKSUM
2678 : : */
2679 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2680 : : * OUTER_IPV4
2681 : : */
2682 : : 0x00, /* OUTER_UDP_CKSUM | OUTER_IPV6 |
2683 : : * OUTER_IPV4 | OUTER_IP_CKSUM
2684 : : */
2685 : : },
2686 : : }};
2687 : :
2688 : : /* Extract olflags to translate to oltype & iltype */
2689 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2690 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2691 : :
2692 : : /*
2693 : : * E(8):OL2_LN(7):OL3_LN(9):E(23):L3_LN(9):L2_LN(7+z)
2694 : : * E(8):OL2_LN(7):OL3_LN(9):E(23):L3_LN(9):L2_LN(7+z)
2695 : : */
2696 : : const uint32x4_t tshft_4 = {
2697 : : 1,
2698 : : 0,
2699 : : 1,
2700 : : 0,
2701 : : };
2702 : : senddesc01_w1 = vshlq_u32(senddesc01_w1, tshft_4);
2703 : : senddesc23_w1 = vshlq_u32(senddesc23_w1, tshft_4);
2704 : :
2705 : : /*
2706 : : * E(32):L3_LEN(8):L2_LEN(7+Z):OL3_LEN(8):OL2_LEN(7+Z)
2707 : : * E(32):L3_LEN(8):L2_LEN(7+Z):OL3_LEN(8):OL2_LEN(7+Z)
2708 : : */
2709 : : const uint8x16_t shuf_mask5 = {
2710 : : 0x6, 0x5, 0x0, 0x1, 0xFF, 0xFF, 0xFF, 0xFF,
2711 : : 0xE, 0xD, 0x8, 0x9, 0xFF, 0xFF, 0xFF, 0xFF,
2712 : : };
2713 : : senddesc01_w1 = vqtbl1q_u8(senddesc01_w1, shuf_mask5);
2714 : : senddesc23_w1 = vqtbl1q_u8(senddesc23_w1, shuf_mask5);
2715 : :
2716 : : /* Extract outer and inner header ol_flags */
2717 : : const uint64x2_t oi_cksum_mask = {
2718 : : 0x1CF0020000000000,
2719 : : 0x1CF0020000000000,
2720 : : };
2721 : :
2722 : : xtmp128 = vandq_u64(xtmp128, oi_cksum_mask);
2723 : : ytmp128 = vandq_u64(ytmp128, oi_cksum_mask);
2724 : :
2725 : : /* Extract OUTER_UDP_CKSUM bit 41 and
2726 : : * move it to bit 61
2727 : : */
2728 : :
2729 : : xtmp128 = xtmp128 | vshlq_n_u64(xtmp128, 20);
2730 : : ytmp128 = ytmp128 | vshlq_n_u64(ytmp128, 20);
2731 : :
2732 : : /* Shift right oltype by 2 and iltype by 4
2733 : : * to start oltype nibble from BIT(58)
2734 : : * instead of BIT(56) and iltype nibble from BIT(48)
2735 : : * instead of BIT(52).
2736 : : */
2737 : : const int8x16_t tshft5 = {
2738 : : 8, 8, 8, 8, 8, 8, -4, -2,
2739 : : 8, 8, 8, 8, 8, 8, -4, -2,
2740 : : };
2741 : :
2742 : : xtmp128 = vshlq_u8(xtmp128, tshft5);
2743 : : ytmp128 = vshlq_u8(ytmp128, tshft5);
2744 : : /*
2745 : : * E(32):L3_LEN(8):L2_LEN(8):OL3_LEN(8):OL2_LEN(8)
2746 : : * E(32):L3_LEN(8):L2_LEN(8):OL3_LEN(8):OL2_LEN(8)
2747 : : */
2748 : : const int8x16_t tshft3 = {
2749 : : -1, 0, -1, 0, 0, 0, 0, 0,
2750 : : -1, 0, -1, 0, 0, 0, 0, 0,
2751 : : };
2752 : :
2753 : : senddesc01_w1 = vshlq_u8(senddesc01_w1, tshft3);
2754 : : senddesc23_w1 = vshlq_u8(senddesc23_w1, tshft3);
2755 : :
2756 : : /* Mark Bit(4) of oltype */
2757 : : const uint64x2_t oi_cksum_mask2 = {
2758 : : 0x1000000000000000,
2759 : : 0x1000000000000000,
2760 : : };
2761 : :
2762 : : xtmp128 = vorrq_u64(xtmp128, oi_cksum_mask2);
2763 : : ytmp128 = vorrq_u64(ytmp128, oi_cksum_mask2);
2764 : :
2765 : : /* Do the lookup */
2766 : : ltypes01 = vqtbl2q_u8(tbl, xtmp128);
2767 : : ltypes23 = vqtbl2q_u8(tbl, ytmp128);
2768 : :
2769 : : /* Pick only relevant fields i.e Bit 48:55 of iltype and
2770 : : * Bit 56:63 of oltype and place it in corresponding
2771 : : * place in senddesc_w1.
2772 : : */
2773 : : const uint8x16_t shuf_mask0 = {
2774 : : 0xFF, 0xFF, 0xFF, 0xFF, 0x7, 0x6, 0xFF, 0xFF,
2775 : : 0xFF, 0xFF, 0xFF, 0xFF, 0xF, 0xE, 0xFF, 0xFF,
2776 : : };
2777 : :
2778 : : ltypes01 = vqtbl1q_u8(ltypes01, shuf_mask0);
2779 : : ltypes23 = vqtbl1q_u8(ltypes23, shuf_mask0);
2780 : :
2781 : : /* Prepare l4ptr, l3ptr, ol4ptr, ol3ptr from
2782 : : * l3len, l2len, ol3len, ol2len.
2783 : : * a [E(32):L3(8):L2(8):OL3(8):OL2(8)]
2784 : : * a = a + (a << 8)
2785 : : * a [E:(L3+L2):(L2+OL3):(OL3+OL2):OL2]
2786 : : * a = a + (a << 16)
2787 : : * a [E:(L3+L2+OL3+OL2):(L2+OL3+OL2):(OL3+OL2):OL2]
2788 : : * => E(32):IL4PTR(8):IL3PTR(8):OL4PTR(8):OL3PTR(8)
2789 : : */
2790 : : senddesc01_w1 = vaddq_u8(senddesc01_w1, vshlq_n_u32(senddesc01_w1, 8));
2791 : : senddesc23_w1 = vaddq_u8(senddesc23_w1, vshlq_n_u32(senddesc23_w1, 8));
2792 : :
2793 : : /* Continue preparing l4ptr, l3ptr, ol4ptr, ol3ptr */
2794 : : senddesc01_w1 = vaddq_u8(senddesc01_w1, vshlq_n_u32(senddesc01_w1, 16));
2795 : : senddesc23_w1 = vaddq_u8(senddesc23_w1, vshlq_n_u32(senddesc23_w1, 16));
2796 : :
2797 : : /* Move ltypes to senddesc*_w1 */
2798 : : senddesc01_w1 = vorrq_u64(senddesc01_w1, ltypes01);
2799 : : senddesc23_w1 = vorrq_u64(senddesc23_w1, ltypes23);
2800 : : }
2801 : :
2802 : : xmask01 = vdupq_n_u64(0);
2803 : : xmask23 = xmask01;
2804 : : asm volatile("LD1 {%[a].H}[0],[%[in]]\n\t"
2805 : : : [a] "+w"(xmask01)
2806 : : : [in] "r"(mbuf0)
2807 : : : "memory");
2808 : :
2809 : : asm volatile("LD1 {%[a].H}[4],[%[in]]\n\t"
2810 : : : [a] "+w"(xmask01)
2811 : : : [in] "r"(mbuf1)
2812 : : : "memory");
2813 : :
2814 : : asm volatile("LD1 {%[b].H}[0],[%[in]]\n\t"
2815 : : : [b] "+w"(xmask23)
2816 : : : [in] "r"(mbuf2)
2817 : : : "memory");
2818 : :
2819 : : asm volatile("LD1 {%[b].H}[4],[%[in]]\n\t"
2820 : : : [b] "+w"(xmask23)
2821 : : : [in] "r"(mbuf3)
2822 : : : "memory");
2823 : : xmask01 = vshlq_n_u64(xmask01, 20);
2824 : : xmask23 = vshlq_n_u64(xmask23, 20);
2825 : :
2826 : : senddesc01_w0 = vorrq_u64(senddesc01_w0, xmask01);
2827 : : senddesc23_w0 = vorrq_u64(senddesc23_w0, xmask23);
2828 : :
2829 : : if (flags & NIX_TX_OFFLOAD_VLAN_QINQ_F) {
2830 : : /* Tx ol_flag for vlan. */
2831 : : const uint64x2_t olv = {RTE_MBUF_F_TX_VLAN, RTE_MBUF_F_TX_VLAN};
2832 : : /* Bit enable for VLAN1 */
2833 : : const uint64x2_t mlv = {BIT_ULL(49), BIT_ULL(49)};
2834 : : /* Tx ol_flag for QnQ. */
2835 : : const uint64x2_t olq = {RTE_MBUF_F_TX_QINQ, RTE_MBUF_F_TX_QINQ};
2836 : : /* Bit enable for VLAN0 */
2837 : : const uint64x2_t mlq = {BIT_ULL(48), BIT_ULL(48)};
2838 : : /* Load vlan values from packet. outer is VLAN 0 */
2839 : : uint64x2_t ext01 = {
2840 : : ((uint32_t)tx_pkts[0]->vlan_tci_outer) << 8 |
2841 : : ((uint64_t)tx_pkts[0]->vlan_tci) << 32,
2842 : : ((uint32_t)tx_pkts[1]->vlan_tci_outer) << 8 |
2843 : : ((uint64_t)tx_pkts[1]->vlan_tci) << 32,
2844 : : };
2845 : : uint64x2_t ext23 = {
2846 : : ((uint32_t)tx_pkts[2]->vlan_tci_outer) << 8 |
2847 : : ((uint64_t)tx_pkts[2]->vlan_tci) << 32,
2848 : : ((uint32_t)tx_pkts[3]->vlan_tci_outer) << 8 |
2849 : : ((uint64_t)tx_pkts[3]->vlan_tci) << 32,
2850 : : };
2851 : :
2852 : : /* Get ol_flags of the packets. */
2853 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2854 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2855 : :
2856 : : /* ORR vlan outer/inner values into cmd. */
2857 : : sendext01_w1 = vorrq_u64(sendext01_w1, ext01);
2858 : : sendext23_w1 = vorrq_u64(sendext23_w1, ext23);
2859 : :
2860 : : /* Test for offload enable bits and generate masks. */
2861 : : xtmp128 = vorrq_u64(vandq_u64(vtstq_u64(xtmp128, olv), mlv),
2862 : : vandq_u64(vtstq_u64(xtmp128, olq), mlq));
2863 : : ytmp128 = vorrq_u64(vandq_u64(vtstq_u64(ytmp128, olv), mlv),
2864 : : vandq_u64(vtstq_u64(ytmp128, olq), mlq));
2865 : :
2866 : : /* Set vlan enable bits into cmd based on mask. */
2867 : : sendext01_w1 = vorrq_u64(sendext01_w1, xtmp128);
2868 : : sendext23_w1 = vorrq_u64(sendext23_w1, ytmp128);
2869 : : }
2870 : :
2871 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
2872 : : /* Tx ol_flag for timestamp. */
2873 : : const uint64x2_t olf = {RTE_MBUF_F_TX_IEEE1588_TMST,
2874 : : RTE_MBUF_F_TX_IEEE1588_TMST};
2875 : : /* Set send mem alg to SUB. */
2876 : : const uint64x2_t alg = {BIT_ULL(59), BIT_ULL(59)};
2877 : : /* Increment send mem address by 8. */
2878 : : const uint64x2_t addr = {0x8, 0x8};
2879 : :
2880 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2881 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2882 : :
2883 : : /* Check if timestamp is requested and generate inverted
2884 : : * mask as we need not make any changes to default cmd
2885 : : * value.
2886 : : */
2887 : : xtmp128 = vmvnq_u32(vtstq_u64(olf, xtmp128));
2888 : : ytmp128 = vmvnq_u32(vtstq_u64(olf, ytmp128));
2889 : :
2890 : : /* Change send mem address to an 8 byte offset when
2891 : : * TSTMP is disabled.
2892 : : */
2893 : : sendmem01_w1 = vaddq_u64(sendmem01_w1, vandq_u64(xtmp128, addr));
2894 : : sendmem23_w1 = vaddq_u64(sendmem23_w1, vandq_u64(ytmp128, addr));
2895 : : /* Change send mem alg to SUB when TSTMP is disabled. */
2896 : : sendmem01_w0 = vorrq_u64(sendmem01_w0, vandq_u64(xtmp128, alg));
2897 : : sendmem23_w0 = vorrq_u64(sendmem23_w0, vandq_u64(ytmp128, alg));
2898 : :
2899 : : cmd3[0] = vzip1q_u64(sendmem01_w0, sendmem01_w1);
2900 : : cmd3[1] = vzip2q_u64(sendmem01_w0, sendmem01_w1);
2901 : : cmd3[2] = vzip1q_u64(sendmem23_w0, sendmem23_w1);
2902 : : cmd3[3] = vzip2q_u64(sendmem23_w0, sendmem23_w1);
2903 : : }
2904 : :
2905 : : if (flags & NIX_TX_OFFLOAD_TSO_F) {
2906 : : const uint64_t lso_fmt = txq->lso_tun_fmt;
2907 : : uint64_t sx_w0[NIX_DESCS_PER_LOOP];
2908 : : uint64_t sd_w1[NIX_DESCS_PER_LOOP];
2909 : :
2910 : : /* Extract SD W1 as we need to set L4 types. */
2911 : : vst1q_u64(sd_w1, senddesc01_w1);
2912 : : vst1q_u64(sd_w1 + 2, senddesc23_w1);
2913 : :
2914 : : /* Extract SX W0 as we need to set LSO fields. */
2915 : : vst1q_u64(sx_w0, sendext01_w0);
2916 : : vst1q_u64(sx_w0 + 2, sendext23_w0);
2917 : :
2918 : : /* Extract ol_flags. */
2919 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
2920 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
2921 : :
2922 : : /* Prepare individual mbufs. */
2923 : : cn20k_nix_prepare_tso(tx_pkts[0], (union nix_send_hdr_w1_u *)&sd_w1[0],
2924 : : (union nix_send_ext_w0_u *)&sx_w0[0],
2925 : : vgetq_lane_u64(xtmp128, 0), flags, lso_fmt);
2926 : :
2927 : : cn20k_nix_prepare_tso(tx_pkts[1], (union nix_send_hdr_w1_u *)&sd_w1[1],
2928 : : (union nix_send_ext_w0_u *)&sx_w0[1],
2929 : : vgetq_lane_u64(xtmp128, 1), flags, lso_fmt);
2930 : :
2931 : : cn20k_nix_prepare_tso(tx_pkts[2], (union nix_send_hdr_w1_u *)&sd_w1[2],
2932 : : (union nix_send_ext_w0_u *)&sx_w0[2],
2933 : : vgetq_lane_u64(ytmp128, 0), flags, lso_fmt);
2934 : :
2935 : : cn20k_nix_prepare_tso(tx_pkts[3], (union nix_send_hdr_w1_u *)&sd_w1[3],
2936 : : (union nix_send_ext_w0_u *)&sx_w0[3],
2937 : : vgetq_lane_u64(ytmp128, 1), flags, lso_fmt);
2938 : :
2939 : : senddesc01_w1 = vld1q_u64(sd_w1);
2940 : : senddesc23_w1 = vld1q_u64(sd_w1 + 2);
2941 : :
2942 : : sendext01_w0 = vld1q_u64(sx_w0);
2943 : : sendext23_w0 = vld1q_u64(sx_w0 + 2);
2944 : : }
2945 : :
2946 : : if ((flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) && !(flags & NIX_TX_MULTI_SEG_F) &&
2947 : : !(flags & NIX_TX_OFFLOAD_SECURITY_F)) {
2948 : : /* Set don't free bit if reference count > 1 */
2949 : : cn20k_nix_prefree_seg_vec(tx_pkts, &extm, txq, &senddesc01_w0,
2950 : : &senddesc23_w0, &senddesc01_w1, &senddesc23_w1);
2951 : : } else if (!(flags & NIX_TX_MULTI_SEG_F) && !(flags & NIX_TX_OFFLOAD_SECURITY_F)) {
2952 : : /* Move mbufs to iova */
2953 : : mbuf0 = (uint64_t *)tx_pkts[0];
2954 : : mbuf1 = (uint64_t *)tx_pkts[1];
2955 : : mbuf2 = (uint64_t *)tx_pkts[2];
2956 : : mbuf3 = (uint64_t *)tx_pkts[3];
2957 : :
2958 : : /* Mark mempool object as "put" since
2959 : : * it is freed by NIX
2960 : : */
2961 : : RTE_MEMPOOL_CHECK_COOKIES(((struct rte_mbuf *)mbuf0)->pool, (void **)&mbuf0,
2962 : : 1, 0);
2963 : :
2964 : : RTE_MEMPOOL_CHECK_COOKIES(((struct rte_mbuf *)mbuf1)->pool, (void **)&mbuf1,
2965 : : 1, 0);
2966 : :
2967 : : RTE_MEMPOOL_CHECK_COOKIES(((struct rte_mbuf *)mbuf2)->pool, (void **)&mbuf2,
2968 : : 1, 0);
2969 : :
2970 : : RTE_MEMPOOL_CHECK_COOKIES(((struct rte_mbuf *)mbuf3)->pool, (void **)&mbuf3,
2971 : : 1, 0);
2972 : : }
2973 : :
2974 : : /* Create 4W cmd for 4 mbufs (sendhdr, sgdesc) */
2975 : : cmd0[0] = vzip1q_u64(senddesc01_w0, senddesc01_w1);
2976 : : cmd0[1] = vzip2q_u64(senddesc01_w0, senddesc01_w1);
2977 : : cmd0[2] = vzip1q_u64(senddesc23_w0, senddesc23_w1);
2978 : : cmd0[3] = vzip2q_u64(senddesc23_w0, senddesc23_w1);
2979 : :
2980 : : cmd1[0] = vzip1q_u64(sgdesc01_w0, sgdesc01_w1);
2981 : : cmd1[1] = vzip2q_u64(sgdesc01_w0, sgdesc01_w1);
2982 : : cmd1[2] = vzip1q_u64(sgdesc23_w0, sgdesc23_w1);
2983 : : cmd1[3] = vzip2q_u64(sgdesc23_w0, sgdesc23_w1);
2984 : :
2985 : : if (flags & NIX_TX_NEED_EXT_HDR) {
2986 : : cmd2[0] = vzip1q_u64(sendext01_w0, sendext01_w1);
2987 : : cmd2[1] = vzip2q_u64(sendext01_w0, sendext01_w1);
2988 : : cmd2[2] = vzip1q_u64(sendext23_w0, sendext23_w1);
2989 : : cmd2[3] = vzip2q_u64(sendext23_w0, sendext23_w1);
2990 : : }
2991 : :
2992 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
2993 : : const uint64x2_t olf = {RTE_MBUF_F_TX_SEC_OFFLOAD,
2994 : : RTE_MBUF_F_TX_SEC_OFFLOAD};
2995 : : uintptr_t next;
2996 : : uint8_t dw;
2997 : :
2998 : : /* Extract ol_flags. */
2999 : : xtmp128 = vzip1q_u64(len_olflags0, len_olflags1);
3000 : : ytmp128 = vzip1q_u64(len_olflags2, len_olflags3);
3001 : :
3002 : : xtmp128 = vtstq_u64(olf, xtmp128);
3003 : : ytmp128 = vtstq_u64(olf, ytmp128);
3004 : :
3005 : : /* Process mbuf0 */
3006 : : dw = cn20k_nix_tx_dwords(flags, segdw[0]);
3007 : : if (vgetq_lane_u64(xtmp128, 0))
3008 : : cn20k_nix_prep_sec_vec(tx_pkts[0], &cmd0[0], &cmd1[0], &next,
3009 : : c_laddr, &c_lnum, &c_loff, &c_shft, sa_base,
3010 : : flags);
3011 : : else
3012 : : cn20k_nix_lmt_next(dw, laddr, &lnum, &loff, &shift, &wd.data128,
3013 : : &next);
3014 : :
3015 : : /* Store mbuf0 to LMTLINE/CPT NIXTX area */
3016 : : cn20k_nix_xmit_store(txq, tx_pkts[0], &extm, segdw[0], next, cmd0[0],
3017 : : cmd1[0], cmd2[0], cmd3[0], flags);
3018 : :
3019 : : /* Process mbuf1 */
3020 : : dw = cn20k_nix_tx_dwords(flags, segdw[1]);
3021 : : if (vgetq_lane_u64(xtmp128, 1))
3022 : : cn20k_nix_prep_sec_vec(tx_pkts[1], &cmd0[1], &cmd1[1], &next,
3023 : : c_laddr, &c_lnum, &c_loff, &c_shft, sa_base,
3024 : : flags);
3025 : : else
3026 : : cn20k_nix_lmt_next(dw, laddr, &lnum, &loff, &shift, &wd.data128,
3027 : : &next);
3028 : :
3029 : : /* Store mbuf1 to LMTLINE/CPT NIXTX area */
3030 : : cn20k_nix_xmit_store(txq, tx_pkts[1], &extm, segdw[1], next, cmd0[1],
3031 : : cmd1[1], cmd2[1], cmd3[1], flags);
3032 : :
3033 : : /* Process mbuf2 */
3034 : : dw = cn20k_nix_tx_dwords(flags, segdw[2]);
3035 : : if (vgetq_lane_u64(ytmp128, 0))
3036 : : cn20k_nix_prep_sec_vec(tx_pkts[2], &cmd0[2], &cmd1[2], &next,
3037 : : c_laddr, &c_lnum, &c_loff, &c_shft, sa_base,
3038 : : flags);
3039 : : else
3040 : : cn20k_nix_lmt_next(dw, laddr, &lnum, &loff, &shift, &wd.data128,
3041 : : &next);
3042 : :
3043 : : /* Store mbuf2 to LMTLINE/CPT NIXTX area */
3044 : : cn20k_nix_xmit_store(txq, tx_pkts[2], &extm, segdw[2], next, cmd0[2],
3045 : : cmd1[2], cmd2[2], cmd3[2], flags);
3046 : :
3047 : : /* Process mbuf3 */
3048 : : dw = cn20k_nix_tx_dwords(flags, segdw[3]);
3049 : : if (vgetq_lane_u64(ytmp128, 1))
3050 : : cn20k_nix_prep_sec_vec(tx_pkts[3], &cmd0[3], &cmd1[3], &next,
3051 : : c_laddr, &c_lnum, &c_loff, &c_shft, sa_base,
3052 : : flags);
3053 : : else
3054 : : cn20k_nix_lmt_next(dw, laddr, &lnum, &loff, &shift, &wd.data128,
3055 : : &next);
3056 : :
3057 : : /* Store mbuf3 to LMTLINE/CPT NIXTX area */
3058 : : cn20k_nix_xmit_store(txq, tx_pkts[3], &extm, segdw[3], next, cmd0[3],
3059 : : cmd1[3], cmd2[3], cmd3[3], flags);
3060 : :
3061 : : } else if (flags & NIX_TX_MULTI_SEG_F) {
3062 : : uint8_t j;
3063 : :
3064 : : segdw[4] = 8;
3065 : : j = cn20k_nix_prep_lmt_mseg_vector(txq, tx_pkts, &extm, cmd0, cmd1, cmd2,
3066 : : cmd3, segdw,
3067 : : (uint64_t *)LMT_OFF(laddr, lnum, 0),
3068 : : &wd.data128, &shift, flags);
3069 : : lnum += j;
3070 : : } else if (flags & NIX_TX_NEED_EXT_HDR) {
3071 : : /* Store the prepared send desc to LMT lines */
3072 : : if (flags & NIX_TX_OFFLOAD_TSTAMP_F) {
3073 : : vst1q_u64(LMT_OFF(laddr, lnum, 0), cmd0[0]);
3074 : : vst1q_u64(LMT_OFF(laddr, lnum, 16), cmd2[0]);
3075 : : vst1q_u64(LMT_OFF(laddr, lnum, 32), cmd1[0]);
3076 : : vst1q_u64(LMT_OFF(laddr, lnum, 48), cmd3[0]);
3077 : : vst1q_u64(LMT_OFF(laddr, lnum, 64), cmd0[1]);
3078 : : vst1q_u64(LMT_OFF(laddr, lnum, 80), cmd2[1]);
3079 : : vst1q_u64(LMT_OFF(laddr, lnum, 96), cmd1[1]);
3080 : : vst1q_u64(LMT_OFF(laddr, lnum, 112), cmd3[1]);
3081 : : lnum += 1;
3082 : : vst1q_u64(LMT_OFF(laddr, lnum, 0), cmd0[2]);
3083 : : vst1q_u64(LMT_OFF(laddr, lnum, 16), cmd2[2]);
3084 : : vst1q_u64(LMT_OFF(laddr, lnum, 32), cmd1[2]);
3085 : : vst1q_u64(LMT_OFF(laddr, lnum, 48), cmd3[2]);
3086 : : vst1q_u64(LMT_OFF(laddr, lnum, 64), cmd0[3]);
3087 : : vst1q_u64(LMT_OFF(laddr, lnum, 80), cmd2[3]);
3088 : : vst1q_u64(LMT_OFF(laddr, lnum, 96), cmd1[3]);
3089 : : vst1q_u64(LMT_OFF(laddr, lnum, 112), cmd3[3]);
3090 : : } else {
3091 : : vst1q_u64(LMT_OFF(laddr, lnum, 0), cmd0[0]);
3092 : : vst1q_u64(LMT_OFF(laddr, lnum, 16), cmd2[0]);
3093 : : vst1q_u64(LMT_OFF(laddr, lnum, 32), cmd1[0]);
3094 : : vst1q_u64(LMT_OFF(laddr, lnum, 48), cmd0[1]);
3095 : : vst1q_u64(LMT_OFF(laddr, lnum, 64), cmd2[1]);
3096 : : vst1q_u64(LMT_OFF(laddr, lnum, 80), cmd1[1]);
3097 : : lnum += 1;
3098 : : vst1q_u64(LMT_OFF(laddr, lnum, 0), cmd0[2]);
3099 : : vst1q_u64(LMT_OFF(laddr, lnum, 16), cmd2[2]);
3100 : : vst1q_u64(LMT_OFF(laddr, lnum, 32), cmd1[2]);
3101 : : vst1q_u64(LMT_OFF(laddr, lnum, 48), cmd0[3]);
3102 : : vst1q_u64(LMT_OFF(laddr, lnum, 64), cmd2[3]);
3103 : : vst1q_u64(LMT_OFF(laddr, lnum, 80), cmd1[3]);
3104 : : }
3105 : : lnum += 1;
3106 : : } else {
3107 : : /* Store the prepared send desc to LMT lines */
3108 : : vst1q_u64(LMT_OFF(laddr, lnum, 0), cmd0[0]);
3109 : : vst1q_u64(LMT_OFF(laddr, lnum, 16), cmd1[0]);
3110 : : vst1q_u64(LMT_OFF(laddr, lnum, 32), cmd0[1]);
3111 : : vst1q_u64(LMT_OFF(laddr, lnum, 48), cmd1[1]);
3112 : : vst1q_u64(LMT_OFF(laddr, lnum, 64), cmd0[2]);
3113 : : vst1q_u64(LMT_OFF(laddr, lnum, 80), cmd1[2]);
3114 : : vst1q_u64(LMT_OFF(laddr, lnum, 96), cmd0[3]);
3115 : : vst1q_u64(LMT_OFF(laddr, lnum, 112), cmd1[3]);
3116 : : lnum += 1;
3117 : : }
3118 : :
3119 : : tx_pkts = tx_pkts + NIX_DESCS_PER_LOOP;
3120 : : }
3121 : :
3122 : : /* Roundup lnum to last line if it is partial */
3123 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
3124 : : lnum = lnum + !!loff;
3125 : : wd.data128 = wd.data128 | (((__uint128_t)(((loff >> 4) - 1) & 0x7) << shift));
3126 : : }
3127 : :
3128 : : if (flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F))
3129 : : wd.data[0] >>= 16;
3130 : :
3131 : : if ((flags & NIX_TX_VWQE_F) && !(ws[3] & BIT_ULL(35)))
3132 : : ws[3] = roc_sso_hws_head_wait(ws[0]);
3133 : :
3134 : : left -= burst;
3135 : :
3136 : : /* Submit CPT instructions if any */
3137 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
3138 : : uint16_t sec_pkts = (c_lnum << 1) + c_loff;
3139 : :
3140 : : if (flags & NIX_TX_VWQE_F)
3141 : : cn20k_nix_vwqe_wait_fc(txq, sec_pkts);
3142 : : cn20k_nix_sec_fc_wait(txq, sec_pkts);
3143 : : cn20k_nix_sec_steorl(c_io_addr, c_lmt_id, c_lnum, c_loff, c_shft);
3144 : : }
3145 : :
3146 : : /* Trigger LMTST */
3147 : : if (lnum > 16) {
3148 : : if (!(flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F)))
3149 : : wd.data[0] = cn20k_nix_tx_steor_vec_data(flags);
3150 : :
3151 : : pa = io_addr | (wd.data[0] & 0x7) << 4;
3152 : : wd.data[0] &= ~0x7ULL;
3153 : :
3154 : : if (flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F))
3155 : : wd.data[0] <<= 16;
3156 : :
3157 : : wd.data[0] |= (15ULL << 12);
3158 : : wd.data[0] |= (uint64_t)lmt_id;
3159 : :
3160 : : if (flags & NIX_TX_VWQE_F)
3161 : : cn20k_nix_vwqe_wait_fc(txq, cn20k_nix_pkts_per_vec_brst(flags) >> 1);
3162 : : /* STEOR0 */
3163 : : roc_lmt_submit_steorl(wd.data[0], pa);
3164 : :
3165 : : if (!(flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F)))
3166 : : wd.data[1] = cn20k_nix_tx_steor_vec_data(flags);
3167 : :
3168 : : pa = io_addr | (wd.data[1] & 0x7) << 4;
3169 : : wd.data[1] &= ~0x7ULL;
3170 : :
3171 : : if (flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F))
3172 : : wd.data[1] <<= 16;
3173 : :
3174 : : wd.data[1] |= ((uint64_t)(lnum - 17)) << 12;
3175 : : wd.data[1] |= (uint64_t)(lmt_id + 16);
3176 : :
3177 : : if (flags & NIX_TX_VWQE_F) {
3178 : : if (flags & NIX_TX_MULTI_SEG_F) {
3179 : : if (burst - (cn20k_nix_pkts_per_vec_brst(flags) >> 1) > 0)
3180 : : cn20k_nix_vwqe_wait_fc(txq,
3181 : : burst - (cn20k_nix_pkts_per_vec_brst(flags) >> 1));
3182 : : } else {
3183 : : cn20k_nix_vwqe_wait_fc(txq,
3184 : : burst - (cn20k_nix_pkts_per_vec_brst(flags) >> 1));
3185 : : }
3186 : : }
3187 : : /* STEOR1 */
3188 : : roc_lmt_submit_steorl(wd.data[1], pa);
3189 : : } else if (lnum) {
3190 : : if (!(flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F)))
3191 : : wd.data[0] = cn20k_nix_tx_steor_vec_data(flags);
3192 : :
3193 : : pa = io_addr | (wd.data[0] & 0x7) << 4;
3194 : : wd.data[0] &= ~0x7ULL;
3195 : :
3196 : : if (flags & (NIX_TX_MULTI_SEG_F | NIX_TX_OFFLOAD_SECURITY_F))
3197 : : wd.data[0] <<= 16;
3198 : :
3199 : : wd.data[0] |= ((uint64_t)(lnum - 1)) << 12;
3200 : : wd.data[0] |= (uint64_t)lmt_id;
3201 : :
3202 : : if (flags & NIX_TX_VWQE_F)
3203 : : cn20k_nix_vwqe_wait_fc(txq, burst);
3204 : : /* STEOR0 */
3205 : : roc_lmt_submit_steorl(wd.data[0], pa);
3206 : : }
3207 : :
3208 : : rte_io_wmb();
3209 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && !txq->tx_compl.ena) {
3210 : : cn20k_nix_free_extmbuf(extm);
3211 : : extm = NULL;
3212 : : }
3213 : :
3214 : : if (left)
3215 : : goto again;
3216 : :
3217 : : if (unlikely(scalar)) {
3218 : : if (flags & NIX_TX_MULTI_SEG_F)
3219 : : pkts += cn20k_nix_xmit_pkts_mseg(tx_queue, ws, tx_pkts, scalar, cmd, flags);
3220 : : else
3221 : : pkts += cn20k_nix_xmit_pkts(tx_queue, ws, tx_pkts, scalar, cmd, flags);
3222 : : }
3223 : :
3224 : : return pkts;
3225 : : }
3226 : :
3227 : : #else
3228 : : static __rte_always_inline uint16_t
3229 : : cn20k_nix_xmit_pkts_vector(void *tx_queue, uint64_t *ws, struct rte_mbuf **tx_pkts, uint16_t pkts,
3230 : : uint64_t *cmd, const uint16_t flags)
3231 : : {
3232 : : RTE_SET_USED(ws);
3233 : : RTE_SET_USED(tx_queue);
3234 : : RTE_SET_USED(tx_pkts);
3235 : : RTE_SET_USED(pkts);
3236 : : RTE_SET_USED(cmd);
3237 : : RTE_SET_USED(flags);
3238 : : return 0;
3239 : : }
3240 : : #endif
3241 : :
3242 : : #define L3L4CSUM_F NIX_TX_OFFLOAD_L3_L4_CSUM_F
3243 : : #define OL3OL4CSUM_F NIX_TX_OFFLOAD_OL3_OL4_CSUM_F
3244 : : #define VLAN_F NIX_TX_OFFLOAD_VLAN_QINQ_F
3245 : : #define NOFF_F NIX_TX_OFFLOAD_MBUF_NOFF_F
3246 : : #define TSO_F NIX_TX_OFFLOAD_TSO_F
3247 : : #define TSP_F NIX_TX_OFFLOAD_TSTAMP_F
3248 : : #define T_SEC_F NIX_TX_OFFLOAD_SECURITY_F
3249 : :
3250 : : /* [T_SEC_F] [TSP] [TSO] [NOFF] [VLAN] [OL3OL4CSUM] [L3L4CSUM] */
3251 : : #define NIX_TX_FASTPATH_MODES_0_15 \
3252 : : T(no_offload, 6, NIX_TX_OFFLOAD_NONE) \
3253 : : T(l3l4csum, 6, L3L4CSUM_F) \
3254 : : T(ol3ol4csum, 6, OL3OL4CSUM_F) \
3255 : : T(ol3ol4csum_l3l4csum, 6, OL3OL4CSUM_F | L3L4CSUM_F) \
3256 : : T(vlan, 6, VLAN_F) \
3257 : : T(vlan_l3l4csum, 6, VLAN_F | L3L4CSUM_F) \
3258 : : T(vlan_ol3ol4csum, 6, VLAN_F | OL3OL4CSUM_F) \
3259 : : T(vlan_ol3ol4csum_l3l4csum, 6, VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3260 : : T(noff, 6, NOFF_F) \
3261 : : T(noff_l3l4csum, 6, NOFF_F | L3L4CSUM_F) \
3262 : : T(noff_ol3ol4csum, 6, NOFF_F | OL3OL4CSUM_F) \
3263 : : T(noff_ol3ol4csum_l3l4csum, 6, NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3264 : : T(noff_vlan, 6, NOFF_F | VLAN_F) \
3265 : : T(noff_vlan_l3l4csum, 6, NOFF_F | VLAN_F | L3L4CSUM_F) \
3266 : : T(noff_vlan_ol3ol4csum, 6, NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3267 : : T(noff_vlan_ol3ol4csum_l3l4csum, 6, NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3268 : :
3269 : : #define NIX_TX_FASTPATH_MODES_16_31 \
3270 : : T(tso, 6, TSO_F) \
3271 : : T(tso_l3l4csum, 6, TSO_F | L3L4CSUM_F) \
3272 : : T(tso_ol3ol4csum, 6, TSO_F | OL3OL4CSUM_F) \
3273 : : T(tso_ol3ol4csum_l3l4csum, 6, TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3274 : : T(tso_vlan, 6, TSO_F | VLAN_F) \
3275 : : T(tso_vlan_l3l4csum, 6, TSO_F | VLAN_F | L3L4CSUM_F) \
3276 : : T(tso_vlan_ol3ol4csum, 6, TSO_F | VLAN_F | OL3OL4CSUM_F) \
3277 : : T(tso_vlan_ol3ol4csum_l3l4csum, 6, TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3278 : : T(tso_noff, 6, TSO_F | NOFF_F) \
3279 : : T(tso_noff_l3l4csum, 6, TSO_F | NOFF_F | L3L4CSUM_F) \
3280 : : T(tso_noff_ol3ol4csum, 6, TSO_F | NOFF_F | OL3OL4CSUM_F) \
3281 : : T(tso_noff_ol3ol4csum_l3l4csum, 6, TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3282 : : T(tso_noff_vlan, 6, TSO_F | NOFF_F | VLAN_F) \
3283 : : T(tso_noff_vlan_l3l4csum, 6, TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3284 : : T(tso_noff_vlan_ol3ol4csum, 6, TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3285 : : T(tso_noff_vlan_ol3ol4csum_l3l4csum, 6, TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3286 : :
3287 : : #define NIX_TX_FASTPATH_MODES_32_47 \
3288 : : T(ts, 8, TSP_F) \
3289 : : T(ts_l3l4csum, 8, TSP_F | L3L4CSUM_F) \
3290 : : T(ts_ol3ol4csum, 8, TSP_F | OL3OL4CSUM_F) \
3291 : : T(ts_ol3ol4csum_l3l4csum, 8, TSP_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3292 : : T(ts_vlan, 8, TSP_F | VLAN_F) \
3293 : : T(ts_vlan_l3l4csum, 8, TSP_F | VLAN_F | L3L4CSUM_F) \
3294 : : T(ts_vlan_ol3ol4csum, 8, TSP_F | VLAN_F | OL3OL4CSUM_F) \
3295 : : T(ts_vlan_ol3ol4csum_l3l4csum, 8, TSP_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3296 : : T(ts_noff, 8, TSP_F | NOFF_F) \
3297 : : T(ts_noff_l3l4csum, 8, TSP_F | NOFF_F | L3L4CSUM_F) \
3298 : : T(ts_noff_ol3ol4csum, 8, TSP_F | NOFF_F | OL3OL4CSUM_F) \
3299 : : T(ts_noff_ol3ol4csum_l3l4csum, 8, TSP_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3300 : : T(ts_noff_vlan, 8, TSP_F | NOFF_F | VLAN_F) \
3301 : : T(ts_noff_vlan_l3l4csum, 8, TSP_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3302 : : T(ts_noff_vlan_ol3ol4csum, 8, TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3303 : : T(ts_noff_vlan_ol3ol4csum_l3l4csum, 8, TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3304 : :
3305 : : #define NIX_TX_FASTPATH_MODES_48_63 \
3306 : : T(ts_tso, 8, TSP_F | TSO_F) \
3307 : : T(ts_tso_l3l4csum, 8, TSP_F | TSO_F | L3L4CSUM_F) \
3308 : : T(ts_tso_ol3ol4csum, 8, TSP_F | TSO_F | OL3OL4CSUM_F) \
3309 : : T(ts_tso_ol3ol4csum_l3l4csum, 8, TSP_F | TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3310 : : T(ts_tso_vlan, 8, TSP_F | TSO_F | VLAN_F) \
3311 : : T(ts_tso_vlan_l3l4csum, 8, TSP_F | TSO_F | VLAN_F | L3L4CSUM_F) \
3312 : : T(ts_tso_vlan_ol3ol4csum, 8, TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F) \
3313 : : T(ts_tso_vlan_ol3ol4csum_l3l4csum, 8, TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3314 : : T(ts_tso_noff, 8, TSP_F | TSO_F | NOFF_F) \
3315 : : T(ts_tso_noff_l3l4csum, 8, TSP_F | TSO_F | NOFF_F | L3L4CSUM_F) \
3316 : : T(ts_tso_noff_ol3ol4csum, 8, TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F) \
3317 : : T(ts_tso_noff_ol3ol4csum_l3l4csum, 8, TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3318 : : T(ts_tso_noff_vlan, 8, TSP_F | TSO_F | NOFF_F | VLAN_F) \
3319 : : T(ts_tso_noff_vlan_l3l4csum, 8, TSP_F | TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3320 : : T(ts_tso_noff_vlan_ol3ol4csum, 8, TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3321 : : T(ts_tso_noff_vlan_ol3ol4csum_l3l4csum, 8, \
3322 : : TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3323 : :
3324 : : #define NIX_TX_FASTPATH_MODES_64_79 \
3325 : : T(sec, 6, T_SEC_F) \
3326 : : T(sec_l3l4csum, 6, T_SEC_F | L3L4CSUM_F) \
3327 : : T(sec_ol3ol4csum, 6, T_SEC_F | OL3OL4CSUM_F) \
3328 : : T(sec_ol3ol4csum_l3l4csum, 6, T_SEC_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3329 : : T(sec_vlan, 6, T_SEC_F | VLAN_F) \
3330 : : T(sec_vlan_l3l4csum, 6, T_SEC_F | VLAN_F | L3L4CSUM_F) \
3331 : : T(sec_vlan_ol3ol4csum, 6, T_SEC_F | VLAN_F | OL3OL4CSUM_F) \
3332 : : T(sec_vlan_ol3ol4csum_l3l4csum, 6, T_SEC_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3333 : : T(sec_noff, 6, T_SEC_F | NOFF_F) \
3334 : : T(sec_noff_l3l4csum, 6, T_SEC_F | NOFF_F | L3L4CSUM_F) \
3335 : : T(sec_noff_ol3ol4csum, 6, T_SEC_F | NOFF_F | OL3OL4CSUM_F) \
3336 : : T(sec_noff_ol3ol4csum_l3l4csum, 6, T_SEC_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3337 : : T(sec_noff_vlan, 6, T_SEC_F | NOFF_F | VLAN_F) \
3338 : : T(sec_noff_vlan_l3l4csum, 6, T_SEC_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3339 : : T(sec_noff_vlan_ol3ol4csum, 6, T_SEC_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3340 : : T(sec_noff_vlan_ol3ol4csum_l3l4csum, 6, \
3341 : : T_SEC_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3342 : :
3343 : : #define NIX_TX_FASTPATH_MODES_80_95 \
3344 : : T(sec_tso, 6, T_SEC_F | TSO_F) \
3345 : : T(sec_tso_l3l4csum, 6, T_SEC_F | TSO_F | L3L4CSUM_F) \
3346 : : T(sec_tso_ol3ol4csum, 6, T_SEC_F | TSO_F | OL3OL4CSUM_F) \
3347 : : T(sec_tso_ol3ol4csum_l3l4csum, 6, T_SEC_F | TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3348 : : T(sec_tso_vlan, 6, T_SEC_F | TSO_F | VLAN_F) \
3349 : : T(sec_tso_vlan_l3l4csum, 6, T_SEC_F | TSO_F | VLAN_F | L3L4CSUM_F) \
3350 : : T(sec_tso_vlan_ol3ol4csum, 6, T_SEC_F | TSO_F | VLAN_F | OL3OL4CSUM_F) \
3351 : : T(sec_tso_vlan_ol3ol4csum_l3l4csum, 6, \
3352 : : T_SEC_F | TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3353 : : T(sec_tso_noff, 6, T_SEC_F | TSO_F | NOFF_F) \
3354 : : T(sec_tso_noff_l3l4csum, 6, T_SEC_F | TSO_F | NOFF_F | L3L4CSUM_F) \
3355 : : T(sec_tso_noff_ol3ol4csum, 6, T_SEC_F | TSO_F | NOFF_F | OL3OL4CSUM_F) \
3356 : : T(sec_tso_noff_ol3ol4csum_l3l4csum, 6, \
3357 : : T_SEC_F | TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3358 : : T(sec_tso_noff_vlan, 6, T_SEC_F | TSO_F | NOFF_F | VLAN_F) \
3359 : : T(sec_tso_noff_vlan_l3l4csum, 6, T_SEC_F | TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3360 : : T(sec_tso_noff_vlan_ol3ol4csum, 6, T_SEC_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3361 : : T(sec_tso_noff_vlan_ol3ol4csum_l3l4csum, 6, \
3362 : : T_SEC_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3363 : :
3364 : : #define NIX_TX_FASTPATH_MODES_96_111 \
3365 : : T(sec_ts, 8, T_SEC_F | TSP_F) \
3366 : : T(sec_ts_l3l4csum, 8, T_SEC_F | TSP_F | L3L4CSUM_F) \
3367 : : T(sec_ts_ol3ol4csum, 8, T_SEC_F | TSP_F | OL3OL4CSUM_F) \
3368 : : T(sec_ts_ol3ol4csum_l3l4csum, 8, T_SEC_F | TSP_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3369 : : T(sec_ts_vlan, 8, T_SEC_F | TSP_F | VLAN_F) \
3370 : : T(sec_ts_vlan_l3l4csum, 8, T_SEC_F | TSP_F | VLAN_F | L3L4CSUM_F) \
3371 : : T(sec_ts_vlan_ol3ol4csum, 8, T_SEC_F | TSP_F | VLAN_F | OL3OL4CSUM_F) \
3372 : : T(sec_ts_vlan_ol3ol4csum_l3l4csum, 8, \
3373 : : T_SEC_F | TSP_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3374 : : T(sec_ts_noff, 8, T_SEC_F | TSP_F | NOFF_F) \
3375 : : T(sec_ts_noff_l3l4csum, 8, T_SEC_F | TSP_F | NOFF_F | L3L4CSUM_F) \
3376 : : T(sec_ts_noff_ol3ol4csum, 8, T_SEC_F | TSP_F | NOFF_F | OL3OL4CSUM_F) \
3377 : : T(sec_ts_noff_ol3ol4csum_l3l4csum, 8, \
3378 : : T_SEC_F | TSP_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3379 : : T(sec_ts_noff_vlan, 8, T_SEC_F | TSP_F | NOFF_F | VLAN_F) \
3380 : : T(sec_ts_noff_vlan_l3l4csum, 8, T_SEC_F | TSP_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3381 : : T(sec_ts_noff_vlan_ol3ol4csum, 8, T_SEC_F | TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3382 : : T(sec_ts_noff_vlan_ol3ol4csum_l3l4csum, 8, \
3383 : : T_SEC_F | TSP_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3384 : :
3385 : : #define NIX_TX_FASTPATH_MODES_112_127 \
3386 : : T(sec_ts_tso, 8, T_SEC_F | TSP_F | TSO_F) \
3387 : : T(sec_ts_tso_l3l4csum, 8, T_SEC_F | TSP_F | TSO_F | L3L4CSUM_F) \
3388 : : T(sec_ts_tso_ol3ol4csum, 8, T_SEC_F | TSP_F | TSO_F | OL3OL4CSUM_F) \
3389 : : T(sec_ts_tso_ol3ol4csum_l3l4csum, 8, T_SEC_F | TSP_F | TSO_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3390 : : T(sec_ts_tso_vlan, 8, T_SEC_F | TSP_F | TSO_F | VLAN_F) \
3391 : : T(sec_ts_tso_vlan_l3l4csum, 8, T_SEC_F | TSP_F | TSO_F | VLAN_F | L3L4CSUM_F) \
3392 : : T(sec_ts_tso_vlan_ol3ol4csum, 8, T_SEC_F | TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F) \
3393 : : T(sec_ts_tso_vlan_ol3ol4csum_l3l4csum, 8, \
3394 : : T_SEC_F | TSP_F | TSO_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3395 : : T(sec_ts_tso_noff, 8, T_SEC_F | TSP_F | TSO_F | NOFF_F) \
3396 : : T(sec_ts_tso_noff_l3l4csum, 8, T_SEC_F | TSP_F | TSO_F | NOFF_F | L3L4CSUM_F) \
3397 : : T(sec_ts_tso_noff_ol3ol4csum, 8, T_SEC_F | TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F) \
3398 : : T(sec_ts_tso_noff_ol3ol4csum_l3l4csum, 8, \
3399 : : T_SEC_F | TSP_F | TSO_F | NOFF_F | OL3OL4CSUM_F | L3L4CSUM_F) \
3400 : : T(sec_ts_tso_noff_vlan, 8, T_SEC_F | TSP_F | TSO_F | NOFF_F | VLAN_F) \
3401 : : T(sec_ts_tso_noff_vlan_l3l4csum, 8, \
3402 : : T_SEC_F | TSP_F | TSO_F | NOFF_F | VLAN_F | L3L4CSUM_F) \
3403 : : T(sec_ts_tso_noff_vlan_ol3ol4csum, 8, \
3404 : : T_SEC_F | TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F) \
3405 : : T(sec_ts_tso_noff_vlan_ol3ol4csum_l3l4csum, 8, \
3406 : : T_SEC_F | TSP_F | TSO_F | NOFF_F | VLAN_F | OL3OL4CSUM_F | L3L4CSUM_F)
3407 : :
3408 : : #define NIX_TX_FASTPATH_MODES \
3409 : : NIX_TX_FASTPATH_MODES_0_15 \
3410 : : NIX_TX_FASTPATH_MODES_16_31 \
3411 : : NIX_TX_FASTPATH_MODES_32_47 \
3412 : : NIX_TX_FASTPATH_MODES_48_63 \
3413 : : NIX_TX_FASTPATH_MODES_64_79 \
3414 : : NIX_TX_FASTPATH_MODES_80_95 \
3415 : : NIX_TX_FASTPATH_MODES_96_111 \
3416 : : NIX_TX_FASTPATH_MODES_112_127
3417 : :
3418 : : #define T(name, sz, flags) \
3419 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_##name( \
3420 : : void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts); \
3421 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_mseg_##name( \
3422 : : void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts); \
3423 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_vec_##name( \
3424 : : void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts); \
3425 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_vec_mseg_##name( \
3426 : : void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t pkts);
3427 : :
3428 : : NIX_TX_FASTPATH_MODES
3429 : : #undef T
3430 : :
3431 : : #define NIX_TX_XMIT(fn, sz, flags) \
3432 : : uint16_t __rte_noinline __rte_hot fn(void *tx_queue, struct rte_mbuf **tx_pkts, \
3433 : : uint16_t pkts) \
3434 : : { \
3435 : : uint64_t cmd[sz]; \
3436 : : /* For TSO inner checksum is a must */ \
3437 : : if (((flags) & NIX_TX_OFFLOAD_TSO_F) && !((flags) & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) \
3438 : : return 0; \
3439 : : return cn20k_nix_xmit_pkts(tx_queue, NULL, tx_pkts, pkts, cmd, flags); \
3440 : : }
3441 : :
3442 : : #define NIX_TX_XMIT_MSEG(fn, sz, flags) \
3443 : : uint16_t __rte_noinline __rte_hot fn(void *tx_queue, struct rte_mbuf **tx_pkts, \
3444 : : uint16_t pkts) \
3445 : : { \
3446 : : uint64_t cmd[(sz) + CNXK_NIX_TX_MSEG_SG_DWORDS - 2]; \
3447 : : /* For TSO inner checksum is a must */ \
3448 : : if (((flags) & NIX_TX_OFFLOAD_TSO_F) && !((flags) & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) \
3449 : : return 0; \
3450 : : return cn20k_nix_xmit_pkts_mseg(tx_queue, NULL, tx_pkts, pkts, cmd, \
3451 : : flags | NIX_TX_MULTI_SEG_F); \
3452 : : }
3453 : :
3454 : : #define NIX_TX_XMIT_VEC(fn, sz, flags) \
3455 : : uint16_t __rte_noinline __rte_hot fn(void *tx_queue, struct rte_mbuf **tx_pkts, \
3456 : : uint16_t pkts) \
3457 : : { \
3458 : : uint64_t cmd[sz]; \
3459 : : /* For TSO inner checksum is a must */ \
3460 : : if (((flags) & NIX_TX_OFFLOAD_TSO_F) && !((flags) & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) \
3461 : : return 0; \
3462 : : return cn20k_nix_xmit_pkts_vector(tx_queue, NULL, tx_pkts, pkts, cmd, (flags)); \
3463 : : }
3464 : :
3465 : : #define NIX_TX_XMIT_VEC_MSEG(fn, sz, flags) \
3466 : : uint16_t __rte_noinline __rte_hot fn(void *tx_queue, struct rte_mbuf **tx_pkts, \
3467 : : uint16_t pkts) \
3468 : : { \
3469 : : uint64_t cmd[(sz) + CNXK_NIX_TX_MSEG_SG_DWORDS - 2]; \
3470 : : /* For TSO inner checksum is a must */ \
3471 : : if (((flags) & NIX_TX_OFFLOAD_TSO_F) && !((flags) & NIX_TX_OFFLOAD_L3_L4_CSUM_F)) \
3472 : : return 0; \
3473 : : return cn20k_nix_xmit_pkts_vector(tx_queue, NULL, tx_pkts, pkts, cmd, \
3474 : : (flags) | NIX_TX_MULTI_SEG_F); \
3475 : : }
3476 : :
3477 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_all_offload(void *tx_queue,
3478 : : struct rte_mbuf **tx_pkts,
3479 : : uint16_t pkts);
3480 : :
3481 : : uint16_t __rte_noinline __rte_hot cn20k_nix_xmit_pkts_vec_all_offload(void *tx_queue,
3482 : : struct rte_mbuf **tx_pkts,
3483 : : uint16_t pkts);
3484 : : #endif /* __CN20K_TX_H__ */
|