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