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