Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #ifndef __CN9K_WORKER_H__
6 : : #define __CN9K_WORKER_H__
7 : :
8 : : #include <rte_eventdev.h>
9 : : #include <rte_vect.h>
10 : :
11 : : #include "cnxk_ethdev.h"
12 : : #include "cnxk_eventdev.h"
13 : : #include "cnxk_worker.h"
14 : : #include "cn9k_cryptodev_ops.h"
15 : :
16 : : #include "cn9k_ethdev.h"
17 : : #include "cn9k_rx.h"
18 : : #include "cn9k_tx.h"
19 : :
20 : : /* SSO Operations */
21 : :
22 : : static __rte_always_inline uint8_t
23 : : cn9k_sso_hws_new_event(struct cn9k_sso_hws *ws, const struct rte_event *ev)
24 : : {
25 : 0 : const uint32_t tag = (uint32_t)ev->event;
26 : 0 : const uint8_t new_tt = ev->sched_type;
27 : 0 : const uint64_t event_ptr = ev->u64;
28 [ # # # # ]: 0 : const uint16_t grp = ev->queue_id;
29 : :
30 : : rte_atomic_thread_fence(__ATOMIC_ACQ_REL);
31 [ # # # # ]: 0 : if (ws->xaq_lmt <= *ws->fc_mem)
32 : : return 0;
33 : :
34 : 0 : cnxk_sso_hws_add_work(event_ptr, tag, new_tt,
35 : 0 : ws->grp_base + (grp << 12));
36 : 0 : return 1;
37 : : }
38 : :
39 : : static __rte_always_inline void
40 : : cn9k_sso_hws_fwd_swtag(uint64_t base, const struct rte_event *ev)
41 : : {
42 : 0 : const uint32_t tag = (uint32_t)ev->event;
43 [ # # # # : 0 : const uint8_t new_tt = ev->sched_type;
# # # # ]
44 : 0 : const uint8_t cur_tt =
45 : 0 : CNXK_TT_FROM_TAG(plt_read64(base + SSOW_LF_GWS_TAG));
46 : :
47 : : /* CNXK model
48 : : * cur_tt/new_tt SSO_TT_ORDERED SSO_TT_ATOMIC SSO_TT_UNTAGGED
49 : : *
50 : : * SSO_TT_ORDERED norm norm untag
51 : : * SSO_TT_ATOMIC norm norm untag
52 : : * SSO_TT_UNTAGGED norm norm NOOP
53 : : */
54 : :
55 [ # # # # : 0 : if (new_tt == SSO_TT_UNTAGGED) {
# # # # ]
56 [ # # # # : 0 : if (cur_tt != SSO_TT_UNTAGGED)
# # # # ]
57 : 0 : cnxk_sso_hws_swtag_untag(base +
58 : : SSOW_LF_GWS_OP_SWTAG_UNTAG);
59 : : } else {
60 : : cnxk_sso_hws_swtag_norm(tag, new_tt,
61 : 0 : base + SSOW_LF_GWS_OP_SWTAG_NORM);
62 : : }
63 : : }
64 : :
65 : : static __rte_always_inline void
66 : : cn9k_sso_hws_new_event_wait(struct cn9k_sso_hws *ws, const struct rte_event *ev)
67 : : {
68 : 0 : const uint32_t tag = (uint32_t)ev->event;
69 : 0 : const uint8_t new_tt = ev->sched_type;
70 : 0 : const uint64_t event_ptr = ev->u64;
71 : 0 : const uint16_t grp = ev->queue_id;
72 : :
73 [ # # # # ]: 0 : while (ws->xaq_lmt <= __atomic_load_n(ws->fc_mem, __ATOMIC_RELAXED))
74 : : ;
75 : :
76 : 0 : cnxk_sso_hws_add_work(event_ptr, tag, new_tt,
77 : 0 : ws->grp_base + (grp << 12));
78 : 0 : }
79 : :
80 : : static __rte_always_inline void
81 : : cn9k_sso_hws_forward_event(struct cn9k_sso_hws *ws, const struct rte_event *ev)
82 : : {
83 : 0 : const uint8_t grp = ev->queue_id;
84 : :
85 : : /* Group hasn't changed, Use SWTAG to forward the event */
86 [ # # # # ]: 0 : if (CNXK_GRP_FROM_TAG(plt_read64(ws->base + SSOW_LF_GWS_TAG)) == grp) {
87 : : cn9k_sso_hws_fwd_swtag(ws->base, ev);
88 : 0 : ws->swtag_req = 1;
89 : : } else {
90 : : /*
91 : : * Group has been changed for group based work pipelining,
92 : : * Use add_work operation to transfer the event to
93 : : * new group/core
94 : : */
95 : : rte_atomic_thread_fence(__ATOMIC_RELEASE);
96 : 0 : roc_sso_hws_head_wait(ws->base);
97 : : cn9k_sso_hws_new_event_wait(ws, ev);
98 : : }
99 : : }
100 : :
101 : : /* Dual ws ops. */
102 : :
103 : : static __rte_always_inline uint8_t
104 : : cn9k_sso_hws_dual_new_event(struct cn9k_sso_hws_dual *dws,
105 : : const struct rte_event *ev)
106 : : {
107 : 0 : const uint32_t tag = (uint32_t)ev->event;
108 : 0 : const uint8_t new_tt = ev->sched_type;
109 : 0 : const uint64_t event_ptr = ev->u64;
110 [ # # # # ]: 0 : const uint16_t grp = ev->queue_id;
111 : :
112 : : rte_atomic_thread_fence(__ATOMIC_ACQ_REL);
113 [ # # # # ]: 0 : if (dws->xaq_lmt <= *dws->fc_mem)
114 : : return 0;
115 : :
116 : 0 : cnxk_sso_hws_add_work(event_ptr, tag, new_tt,
117 : 0 : dws->grp_base + (grp << 12));
118 : 0 : return 1;
119 : : }
120 : :
121 : : static __rte_always_inline void
122 : : cn9k_sso_hws_dual_new_event_wait(struct cn9k_sso_hws_dual *dws,
123 : : const struct rte_event *ev)
124 : : {
125 : 0 : const uint32_t tag = (uint32_t)ev->event;
126 : 0 : const uint8_t new_tt = ev->sched_type;
127 : 0 : const uint64_t event_ptr = ev->u64;
128 : 0 : const uint16_t grp = ev->queue_id;
129 : :
130 [ # # # # ]: 0 : while (dws->xaq_lmt <= __atomic_load_n(dws->fc_mem, __ATOMIC_RELAXED))
131 : : ;
132 : :
133 : 0 : cnxk_sso_hws_add_work(event_ptr, tag, new_tt,
134 : 0 : dws->grp_base + (grp << 12));
135 : 0 : }
136 : :
137 : : static __rte_always_inline void
138 : : cn9k_sso_hws_dual_forward_event(struct cn9k_sso_hws_dual *dws, uint64_t base,
139 : : const struct rte_event *ev)
140 : : {
141 : 0 : const uint8_t grp = ev->queue_id;
142 : :
143 : : /* Group hasn't changed, Use SWTAG to forward the event */
144 [ # # # # ]: 0 : if (CNXK_GRP_FROM_TAG(plt_read64(base + SSOW_LF_GWS_TAG)) == grp) {
145 : : cn9k_sso_hws_fwd_swtag(base, ev);
146 : 0 : dws->swtag_req = 1;
147 : : } else {
148 : : /*
149 : : * Group has been changed for group based work pipelining,
150 : : * Use add_work operation to transfer the event to
151 : : * new group/core
152 : : */
153 : : rte_atomic_thread_fence(__ATOMIC_RELEASE);
154 : : roc_sso_hws_head_wait(base);
155 : : cn9k_sso_hws_dual_new_event_wait(dws, ev);
156 : : }
157 : : }
158 : :
159 : : static __rte_always_inline void
160 : : cn9k_wqe_to_mbuf(uint64_t wqe, const uint64_t mbuf, uint8_t port_id,
161 : : const uint32_t tag, const uint32_t flags,
162 : : const void *const lookup_mem)
163 : : {
164 : 0 : const uint64_t mbuf_init = 0x100010000ULL | RTE_PKTMBUF_HEADROOM |
165 : 0 : (flags & NIX_RX_OFFLOAD_TSTAMP_F ? 8 : 0);
166 : :
167 : 0 : cn9k_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag,
168 : : (struct rte_mbuf *)mbuf, lookup_mem,
169 : 0 : mbuf_init | ((uint64_t)port_id) << 48, flags);
170 : : }
171 : :
172 : : static void
173 : 0 : cn9k_sso_process_tstamp(uint64_t u64, uint64_t mbuf,
174 : : struct cnxk_timesync_info *tstamp)
175 : : {
176 : : uint64_t tstamp_ptr;
177 : : uint8_t laptr;
178 : :
179 : 0 : laptr = (uint8_t) *
180 : 0 : (uint64_t *)(u64 + (CNXK_SSO_WQE_LAYR_PTR * sizeof(uint64_t)));
181 [ # # ]: 0 : if (laptr == sizeof(uint64_t)) {
182 : : /* Extracting tstamp, if PTP enabled*/
183 : 0 : tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)u64) +
184 : : CNXK_SSO_WQE_SG_PTR);
185 [ # # ]: 0 : cn9k_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, true,
186 : : (uint64_t *)tstamp_ptr);
187 : : }
188 : 0 : }
189 : :
190 : : static __rte_always_inline void
191 : : cn9k_sso_hws_post_process(uint64_t *u64, uint64_t mbuf, const uint32_t flags,
192 : : const void *const lookup_mem,
193 : : struct cnxk_timesync_info **tstamp)
194 : : {
195 : 0 : u64[0] = (u64[0] & (0x3ull << 32)) << 6 |
196 : 0 : (u64[0] & (0x3FFull << 36)) << 4 | (u64[0] & 0xffffffff);
197 [ # # # # ]: 0 : if (CNXK_EVENT_TYPE_FROM_TAG(u64[0]) == RTE_EVENT_TYPE_CRYPTODEV) {
198 : 0 : u64[1] = cn9k_cpt_crypto_adapter_dequeue(u64[1]);
199 [ # # # # ]: 0 : } else if (CNXK_EVENT_TYPE_FROM_TAG(u64[0]) == RTE_EVENT_TYPE_ETHDEV) {
200 : 0 : uint8_t port = CNXK_SUB_EVENT_FROM_TAG(u64[0]);
201 : :
202 : 0 : u64[0] = CNXK_CLR_SUB_EVENT(u64[0]);
203 [ # # # # ]: 0 : cn9k_wqe_to_mbuf(u64[1], mbuf, port, u64[0] & 0xFFFFF, flags,
204 : : lookup_mem);
205 [ # # # # ]: 0 : if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
206 : 0 : cn9k_sso_process_tstamp(u64[1], mbuf, tstamp[port]);
207 : : u64[1] = mbuf;
208 : : }
209 : : }
210 : :
211 : : static __rte_always_inline uint16_t
212 : : cn9k_sso_hws_dual_get_work(uint64_t base, uint64_t pair_base,
213 : : struct rte_event *ev, const uint32_t flags,
214 : : struct cn9k_sso_hws_dual *dws)
215 : : {
216 : : union {
217 : : __uint128_t get_work;
218 : : uint64_t u64[2];
219 : : } gw;
220 : : uint64_t mbuf;
221 : :
222 : : if (flags & NIX_RX_OFFLOAD_PTYPE_F)
223 : : rte_prefetch_non_temporal(dws->lookup_mem);
224 : : #ifdef RTE_ARCH_ARM64
225 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
226 : : ".Lrty%=: \n"
227 : : " ldr %[tag], [%[tag_loc]] \n"
228 : : " ldr %[wqp], [%[wqp_loc]] \n"
229 : : " tbnz %[tag], 63, .Lrty%= \n"
230 : : ".Ldone%=: str %[gw], [%[pong]] \n"
231 : : " dmb ld \n"
232 : : " sub %[mbuf], %[wqp], #0x80 \n"
233 : : " prfm pldl1keep, [%[mbuf]] \n"
234 : : : [tag] "=&r"(gw.u64[0]), [wqp] "=&r"(gw.u64[1]),
235 : : [mbuf] "=&r"(mbuf)
236 : : : [tag_loc] "r"(base + SSOW_LF_GWS_TAG),
237 : : [wqp_loc] "r"(base + SSOW_LF_GWS_WQP),
238 : : [gw] "r"(dws->gw_wdata),
239 : : [pong] "r"(pair_base + SSOW_LF_GWS_OP_GET_WORK0));
240 : : #else
241 : : gw.u64[0] = plt_read64(base + SSOW_LF_GWS_TAG);
242 : : while ((BIT_ULL(63)) & gw.u64[0])
243 : : gw.u64[0] = plt_read64(base + SSOW_LF_GWS_TAG);
244 : : gw.u64[1] = plt_read64(base + SSOW_LF_GWS_WQP);
245 : : plt_write64(dws->gw_wdata, pair_base + SSOW_LF_GWS_OP_GET_WORK0);
246 : : mbuf = (uint64_t)((char *)gw.u64[1] - sizeof(struct rte_mbuf));
247 : : #endif
248 : :
249 : : if (gw.u64[1])
250 : : cn9k_sso_hws_post_process(gw.u64, mbuf, flags, dws->lookup_mem,
251 : : dws->tstamp);
252 : :
253 : : ev->event = gw.u64[0];
254 : : ev->u64 = gw.u64[1];
255 : :
256 : : return !!gw.u64[1];
257 : : }
258 : :
259 : : static __rte_always_inline uint16_t
260 : : cn9k_sso_hws_get_work(struct cn9k_sso_hws *ws, struct rte_event *ev,
261 : : const uint32_t flags, const void *const lookup_mem)
262 : : {
263 : : union {
264 : : __uint128_t get_work;
265 : : uint64_t u64[2];
266 : : } gw;
267 : : uint64_t mbuf;
268 : :
269 : : plt_write64(ws->gw_wdata, ws->base + SSOW_LF_GWS_OP_GET_WORK0);
270 : :
271 : : if (flags & NIX_RX_OFFLOAD_PTYPE_F)
272 : : rte_prefetch_non_temporal(lookup_mem);
273 : : #ifdef RTE_ARCH_ARM64
274 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
275 : : " ldr %[tag], [%[tag_loc]] \n"
276 : : " ldr %[wqp], [%[wqp_loc]] \n"
277 : : " tbz %[tag], 63, .Ldone%= \n"
278 : : " sevl \n"
279 : : ".Lrty%=: wfe \n"
280 : : " ldr %[tag], [%[tag_loc]] \n"
281 : : " ldr %[wqp], [%[wqp_loc]] \n"
282 : : " tbnz %[tag], 63, .Lrty%= \n"
283 : : ".Ldone%=: dmb ld \n"
284 : : " sub %[mbuf], %[wqp], #0x80 \n"
285 : : " prfm pldl1keep, [%[mbuf]] \n"
286 : : : [tag] "=&r"(gw.u64[0]), [wqp] "=&r"(gw.u64[1]),
287 : : [mbuf] "=&r"(mbuf)
288 : : : [tag_loc] "r"(ws->base + SSOW_LF_GWS_TAG),
289 : : [wqp_loc] "r"(ws->base + SSOW_LF_GWS_WQP));
290 : : #else
291 : : gw.u64[0] = plt_read64(ws->base + SSOW_LF_GWS_TAG);
292 : : while ((BIT_ULL(63)) & gw.u64[0])
293 : : gw.u64[0] = plt_read64(ws->base + SSOW_LF_GWS_TAG);
294 : :
295 : : gw.u64[1] = plt_read64(ws->base + SSOW_LF_GWS_WQP);
296 : : mbuf = (uint64_t)((char *)gw.u64[1] - sizeof(struct rte_mbuf));
297 : : #endif
298 : :
299 : : if (gw.u64[1])
300 : : cn9k_sso_hws_post_process(gw.u64, mbuf, flags, lookup_mem,
301 : : ws->tstamp);
302 : :
303 : : ev->event = gw.u64[0];
304 : : ev->u64 = gw.u64[1];
305 : :
306 : : return !!gw.u64[1];
307 : : }
308 : :
309 : : /* Used in cleaning up workslot. */
310 : : static __rte_always_inline uint16_t
311 : : cn9k_sso_hws_get_work_empty(uint64_t base, struct rte_event *ev,
312 : : const uint32_t flags, void *lookup_mem,
313 : : struct cnxk_timesync_info **tstamp)
314 : : {
315 : : union {
316 : : __uint128_t get_work;
317 : : uint64_t u64[2];
318 : : } gw;
319 : : uint64_t mbuf;
320 : :
321 : : #ifdef RTE_ARCH_ARM64
322 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
323 : : " ldr %[tag], [%[tag_loc]] \n"
324 : : " ldr %[wqp], [%[wqp_loc]] \n"
325 : : " tbz %[tag], 63, .Ldone%= \n"
326 : : " sevl \n"
327 : : ".Lrty%=: wfe \n"
328 : : " ldr %[tag], [%[tag_loc]] \n"
329 : : " ldr %[wqp], [%[wqp_loc]] \n"
330 : : " tbnz %[tag], 63, .Lrty%= \n"
331 : : ".Ldone%=: dmb ld \n"
332 : : " sub %[mbuf], %[wqp], #0x80 \n"
333 : : : [tag] "=&r"(gw.u64[0]), [wqp] "=&r"(gw.u64[1]),
334 : : [mbuf] "=&r"(mbuf)
335 : : : [tag_loc] "r"(base + SSOW_LF_GWS_TAG),
336 : : [wqp_loc] "r"(base + SSOW_LF_GWS_WQP));
337 : : #else
338 : 0 : gw.u64[0] = plt_read64(base + SSOW_LF_GWS_TAG);
339 [ # # # # ]: 0 : while ((BIT_ULL(63)) & gw.u64[0])
340 : : gw.u64[0] = plt_read64(base + SSOW_LF_GWS_TAG);
341 : :
342 [ # # # # ]: 0 : gw.u64[1] = plt_read64(base + SSOW_LF_GWS_WQP);
343 : 0 : mbuf = (uint64_t)((char *)gw.u64[1] - sizeof(struct rte_mbuf));
344 : : #endif
345 : :
346 [ # # # # ]: 0 : if (gw.u64[1])
347 : : cn9k_sso_hws_post_process(gw.u64, mbuf, flags, lookup_mem, tstamp);
348 : : else
349 : 0 : gw.u64[0] = (gw.u64[0] & (0x3ull << 32)) << 6 |
350 : 0 : (gw.u64[0] & (0x3FFull << 36)) << 4 | (gw.u64[0] & 0xffffffff);
351 : :
352 [ # # ]: 0 : ev->event = gw.u64[0];
353 : : ev->u64 = gw.u64[1];
354 : :
355 : : return !!gw.u64[1];
356 : : }
357 : :
358 : : /* CN9K Fastpath functions. */
359 : : uint16_t __rte_hot cn9k_sso_hws_enq(void *port, const struct rte_event *ev);
360 : : uint16_t __rte_hot cn9k_sso_hws_enq_burst(void *port,
361 : : const struct rte_event ev[],
362 : : uint16_t nb_events);
363 : : uint16_t __rte_hot cn9k_sso_hws_enq_new_burst(void *port,
364 : : const struct rte_event ev[],
365 : : uint16_t nb_events);
366 : : uint16_t __rte_hot cn9k_sso_hws_enq_fwd_burst(void *port,
367 : : const struct rte_event ev[],
368 : : uint16_t nb_events);
369 : : int __rte_hot cn9k_sso_hws_profile_switch(void *port, uint8_t profile);
370 : :
371 : : uint16_t __rte_hot cn9k_sso_hws_dual_enq(void *port,
372 : : const struct rte_event *ev);
373 : : uint16_t __rte_hot cn9k_sso_hws_dual_enq_burst(void *port,
374 : : const struct rte_event ev[],
375 : : uint16_t nb_events);
376 : : uint16_t __rte_hot cn9k_sso_hws_dual_enq_new_burst(void *port,
377 : : const struct rte_event ev[],
378 : : uint16_t nb_events);
379 : : uint16_t __rte_hot cn9k_sso_hws_dual_enq_fwd_burst(void *port,
380 : : const struct rte_event ev[],
381 : : uint16_t nb_events);
382 : : uint16_t __rte_hot cn9k_sso_hws_ca_enq(void *port, struct rte_event ev[],
383 : : uint16_t nb_events);
384 : : uint16_t __rte_hot cn9k_sso_hws_dual_ca_enq(void *port, struct rte_event ev[],
385 : : uint16_t nb_events);
386 : : int __rte_hot cn9k_sso_hws_dual_profile_switch(void *port, uint8_t profile);
387 : :
388 : : #define R(name, flags) \
389 : : uint16_t __rte_hot cn9k_sso_hws_deq_##name( \
390 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
391 : : uint16_t __rte_hot cn9k_sso_hws_deq_burst_##name( \
392 : : void *port, struct rte_event ev[], uint16_t nb_events, \
393 : : uint64_t timeout_ticks); \
394 : : uint16_t __rte_hot cn9k_sso_hws_deq_tmo_##name( \
395 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
396 : : uint16_t __rte_hot cn9k_sso_hws_deq_tmo_burst_##name( \
397 : : void *port, struct rte_event ev[], uint16_t nb_events, \
398 : : uint64_t timeout_ticks); \
399 : : uint16_t __rte_hot cn9k_sso_hws_deq_seg_##name( \
400 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
401 : : uint16_t __rte_hot cn9k_sso_hws_deq_seg_burst_##name( \
402 : : void *port, struct rte_event ev[], uint16_t nb_events, \
403 : : uint64_t timeout_ticks); \
404 : : uint16_t __rte_hot cn9k_sso_hws_deq_tmo_seg_##name( \
405 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
406 : : uint16_t __rte_hot cn9k_sso_hws_deq_tmo_seg_burst_##name( \
407 : : void *port, struct rte_event ev[], uint16_t nb_events, \
408 : : uint64_t timeout_ticks);
409 : :
410 : : NIX_RX_FASTPATH_MODES
411 : : #undef R
412 : :
413 : : #define SSO_DEQ(fn, flags) \
414 : : uint16_t __rte_hot fn(void *port, struct rte_event *ev, \
415 : : uint64_t timeout_ticks) \
416 : : { \
417 : : struct cn9k_sso_hws *ws = port; \
418 : : RTE_SET_USED(timeout_ticks); \
419 : : if (ws->swtag_req) { \
420 : : ws->swtag_req = 0; \
421 : : cnxk_sso_hws_swtag_wait(ws->base + SSOW_LF_GWS_TAG); \
422 : : return 1; \
423 : : } \
424 : : return cn9k_sso_hws_get_work(ws, ev, flags, ws->lookup_mem); \
425 : : }
426 : :
427 : : #define SSO_DEQ_SEG(fn, flags) SSO_DEQ(fn, flags | NIX_RX_MULTI_SEG_F)
428 : :
429 : : #define SSO_DEQ_TMO(fn, flags) \
430 : : uint16_t __rte_hot fn(void *port, struct rte_event *ev, \
431 : : uint64_t timeout_ticks) \
432 : : { \
433 : : struct cn9k_sso_hws *ws = port; \
434 : : uint16_t ret = 1; \
435 : : uint64_t iter; \
436 : : if (ws->swtag_req) { \
437 : : ws->swtag_req = 0; \
438 : : cnxk_sso_hws_swtag_wait(ws->base + SSOW_LF_GWS_TAG); \
439 : : return ret; \
440 : : } \
441 : : ret = cn9k_sso_hws_get_work(ws, ev, flags, ws->lookup_mem); \
442 : : for (iter = 1; iter < timeout_ticks && (ret == 0); iter++) \
443 : : ret = cn9k_sso_hws_get_work(ws, ev, flags, \
444 : : ws->lookup_mem); \
445 : : return ret; \
446 : : }
447 : :
448 : : #define SSO_DEQ_TMO_SEG(fn, flags) SSO_DEQ_TMO(fn, flags | NIX_RX_MULTI_SEG_F)
449 : :
450 : : #define R(name, flags) \
451 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_##name( \
452 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
453 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_burst_##name( \
454 : : void *port, struct rte_event ev[], uint16_t nb_events, \
455 : : uint64_t timeout_ticks); \
456 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_tmo_##name( \
457 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
458 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_tmo_burst_##name( \
459 : : void *port, struct rte_event ev[], uint16_t nb_events, \
460 : : uint64_t timeout_ticks); \
461 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_seg_##name( \
462 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
463 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_seg_burst_##name( \
464 : : void *port, struct rte_event ev[], uint16_t nb_events, \
465 : : uint64_t timeout_ticks); \
466 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_tmo_seg_##name( \
467 : : void *port, struct rte_event *ev, uint64_t timeout_ticks); \
468 : : uint16_t __rte_hot cn9k_sso_hws_dual_deq_tmo_seg_burst_##name( \
469 : : void *port, struct rte_event ev[], uint16_t nb_events, \
470 : : uint64_t timeout_ticks);
471 : :
472 : : NIX_RX_FASTPATH_MODES
473 : : #undef R
474 : :
475 : : #define SSO_DUAL_DEQ(fn, flags) \
476 : : uint16_t __rte_hot fn(void *port, struct rte_event *ev, \
477 : : uint64_t timeout_ticks) \
478 : : { \
479 : : struct cn9k_sso_hws_dual *dws = port; \
480 : : uint16_t gw; \
481 : : RTE_SET_USED(timeout_ticks); \
482 : : if (dws->swtag_req) { \
483 : : dws->swtag_req = 0; \
484 : : cnxk_sso_hws_swtag_wait(dws->base[!dws->vws] + \
485 : : SSOW_LF_GWS_TAG); \
486 : : return 1; \
487 : : } \
488 : : gw = cn9k_sso_hws_dual_get_work(dws->base[dws->vws], \
489 : : dws->base[!dws->vws], ev, \
490 : : flags, dws); \
491 : : dws->vws = !dws->vws; \
492 : : return gw; \
493 : : }
494 : :
495 : : #define SSO_DUAL_DEQ_SEG(fn, flags) SSO_DUAL_DEQ(fn, flags | NIX_RX_MULTI_SEG_F)
496 : :
497 : : #define SSO_DUAL_DEQ_TMO(fn, flags) \
498 : : uint16_t __rte_hot fn(void *port, struct rte_event *ev, \
499 : : uint64_t timeout_ticks) \
500 : : { \
501 : : struct cn9k_sso_hws_dual *dws = port; \
502 : : uint16_t ret = 1; \
503 : : uint64_t iter; \
504 : : if (dws->swtag_req) { \
505 : : dws->swtag_req = 0; \
506 : : cnxk_sso_hws_swtag_wait(dws->base[!dws->vws] + \
507 : : SSOW_LF_GWS_TAG); \
508 : : return ret; \
509 : : } \
510 : : ret = cn9k_sso_hws_dual_get_work(dws->base[dws->vws], \
511 : : dws->base[!dws->vws], ev, \
512 : : flags, dws); \
513 : : dws->vws = !dws->vws; \
514 : : for (iter = 1; iter < timeout_ticks && (ret == 0); iter++) { \
515 : : ret = cn9k_sso_hws_dual_get_work(dws->base[dws->vws], \
516 : : dws->base[!dws->vws], \
517 : : ev, flags, dws); \
518 : : dws->vws = !dws->vws; \
519 : : } \
520 : : return ret; \
521 : : }
522 : :
523 : : #define SSO_DUAL_DEQ_TMO_SEG(fn, flags) \
524 : : SSO_DUAL_DEQ_TMO(fn, flags | NIX_RX_MULTI_SEG_F)
525 : :
526 : : #define SSO_CMN_DEQ_BURST(fnb, fn, flags) \
527 : : uint16_t __rte_hot fnb(void *port, struct rte_event ev[], \
528 : : uint16_t nb_events, uint64_t timeout_ticks) \
529 : : { \
530 : : RTE_SET_USED(nb_events); \
531 : : return fn(port, ev, timeout_ticks); \
532 : : }
533 : :
534 : : #define SSO_CMN_DEQ_SEG_BURST(fnb, fn, flags) \
535 : : uint16_t __rte_hot fnb(void *port, struct rte_event ev[], \
536 : : uint16_t nb_events, uint64_t timeout_ticks) \
537 : : { \
538 : : RTE_SET_USED(nb_events); \
539 : : return fn(port, ev, timeout_ticks); \
540 : : }
541 : :
542 : : static __rte_always_inline void
543 : : cn9k_sso_txq_fc_wait(const struct cn9k_eth_txq *txq)
544 : : {
545 : : int64_t avail;
546 : :
547 : : #ifdef RTE_ARCH_ARM64
548 : : int64_t val;
549 : :
550 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
551 : : " ldxr %[val], [%[addr]] \n"
552 : : " sub %[val], %[adj], %[val] \n"
553 : : " lsl %[refill], %[val], %[shft] \n"
554 : : " sub %[refill], %[refill], %[val] \n"
555 : : " cmp %[refill], #0x0 \n"
556 : : " b.gt .Ldne%= \n"
557 : : " sevl \n"
558 : : ".Lrty%=: wfe \n"
559 : : " ldxr %[val], [%[addr]] \n"
560 : : " sub %[val], %[adj], %[val] \n"
561 : : " lsl %[refill], %[val], %[shft] \n"
562 : : " sub %[refill], %[refill], %[val] \n"
563 : : " cmp %[refill], #0x0 \n"
564 : : " b.le .Lrty%= \n"
565 : : ".Ldne%=: \n"
566 : : : [refill] "=&r"(avail), [val] "=&r" (val)
567 : : : [addr] "r"(txq->fc_mem), [adj] "r"(txq->nb_sqb_bufs_adj),
568 : : [shft] "r"(txq->sqes_per_sqb_log2)
569 : : : "memory");
570 : : #else
571 : : do {
572 : : avail = txq->nb_sqb_bufs_adj - __atomic_load_n(txq->fc_mem, __ATOMIC_RELAXED);
573 : : } while (((avail << txq->sqes_per_sqb_log2) - avail) <= 0);
574 : : #endif
575 : : }
576 : :
577 : : static __rte_always_inline struct cn9k_eth_txq *
578 : : cn9k_sso_hws_xtract_meta(struct rte_mbuf *m, uint64_t *txq_data)
579 : : {
580 : : return (struct cn9k_eth_txq
581 : : *)(txq_data[(txq_data[m->port] >> 48) +
582 : : rte_event_eth_tx_adapter_txq_get(m)] &
583 : : (BIT_ULL(48) - 1));
584 : : }
585 : :
586 : : #if defined(RTE_ARCH_ARM64)
587 : :
588 : : static __rte_always_inline void
589 : : cn9k_sso_hws_xmit_sec_one(const struct cn9k_eth_txq *txq, uint64_t base,
590 : : struct rte_mbuf *m, uint64_t *cmd,
591 : : uint32_t flags)
592 : : {
593 : : struct cn9k_outb_priv_data *outb_priv;
594 : : rte_iova_t io_addr = txq->cpt_io_addr;
595 : : uint64_t *lmt_addr = txq->lmt_addr;
596 : : struct cn9k_sec_sess_priv mdata;
597 : : struct nix_send_hdr_s *send_hdr;
598 : : uint64_t sa_base = txq->sa_base;
599 : : uint32_t pkt_len, dlen_adj, rlen;
600 : : struct roc_ie_on_outb_hdr *hdr;
601 : : uint64x2_t cmd01, cmd23;
602 : : uint64_t lmt_status, sa;
603 : : union nix_send_sg_s *sg;
604 : : uint32_t esn_lo, esn_hi;
605 : : uintptr_t dptr, nixtx;
606 : : uint64_t ucode_cmd[4];
607 : : uint64_t esn;
608 : : uint8_t l2_len;
609 : :
610 : : mdata.u64 = *rte_security_dynfield(m);
611 : : send_hdr = (struct nix_send_hdr_s *)cmd;
612 : : if (flags & NIX_TX_NEED_EXT_HDR)
613 : : sg = (union nix_send_sg_s *)&cmd[4];
614 : : else
615 : : sg = (union nix_send_sg_s *)&cmd[2];
616 : :
617 : : if (flags & NIX_TX_NEED_SEND_HDR_W1)
618 : : l2_len = cmd[1] & 0xFF;
619 : : else
620 : : l2_len = m->l2_len;
621 : :
622 : : /* Retrieve DPTR */
623 : : dptr = *(uint64_t *)(sg + 1);
624 : : pkt_len = send_hdr->w0.total;
625 : :
626 : : /* Calculate rlen */
627 : : rlen = pkt_len - l2_len;
628 : : rlen = (rlen + mdata.roundup_len) + (mdata.roundup_byte - 1);
629 : : rlen &= ~(uint64_t)(mdata.roundup_byte - 1);
630 : : rlen += mdata.partial_len;
631 : : dlen_adj = rlen - pkt_len + l2_len;
632 : :
633 : : /* Update send descriptors. Security is single segment only */
634 : : send_hdr->w0.total = pkt_len + dlen_adj;
635 : : sg->seg1_size = pkt_len + dlen_adj;
636 : :
637 : : /* Get area where NIX descriptor needs to be stored */
638 : : nixtx = dptr + pkt_len + dlen_adj;
639 : : nixtx += BIT_ULL(7);
640 : : nixtx = (nixtx - 1) & ~(BIT_ULL(7) - 1);
641 : :
642 : : roc_lmt_mov_nv((void *)(nixtx + 16), cmd, cn9k_nix_tx_ext_subs(flags));
643 : :
644 : : /* Load opcode and cptr already prepared at pkt metadata set */
645 : : pkt_len -= l2_len;
646 : : pkt_len += (sizeof(struct roc_ie_on_outb_hdr) - ROC_IE_ON_MAX_IV_LEN) +
647 : : ROC_ONF_IPSEC_OUTB_MAX_L2_INFO_SZ;
648 : : sa_base &= ~(ROC_NIX_INL_SA_BASE_ALIGN - 1);
649 : :
650 : : sa = (uintptr_t)roc_nix_inl_on_ipsec_outb_sa(sa_base, mdata.sa_idx);
651 : : ucode_cmd[3] = (ROC_CPT_DFLT_ENG_GRP_SE_IE << 61 | sa);
652 : : ucode_cmd[0] = (((ROC_IE_ON_OUTB_MAX_CTX_LEN << 8) |
653 : : ROC_IE_ON_MAJOR_OP_PROCESS_OUTBOUND_IPSEC)
654 : : << 48 |
655 : : (ROC_IE_ON_OUTB_IKEV2_SINGLE_SA_SUPPORT |
656 : : (ROC_ONF_IPSEC_OUTB_MAX_L2_INFO_SZ >>
657 : : 3)) << 32 |
658 : : pkt_len);
659 : :
660 : : /* CPT Word 0 and Word 1 */
661 : : cmd01 = vdupq_n_u64((nixtx + 16) | (cn9k_nix_tx_ext_subs(flags) + 1));
662 : : /* CPT_RES_S is 16B above NIXTX */
663 : : cmd01 = vsetq_lane_u8(nixtx & BIT_ULL(7), cmd01, 8);
664 : :
665 : : /* CPT word 2 and 3 */
666 : : cmd23 = vdupq_n_u64(0);
667 : : cmd23 = vsetq_lane_u64((((uint64_t)RTE_EVENT_TYPE_CPU << 28) |
668 : : CNXK_ETHDEV_SEC_OUTB_EV_SUB << 20),
669 : : cmd23, 0);
670 : : cmd23 = vsetq_lane_u64(((uintptr_t)m + sizeof(struct rte_mbuf)) | 1,
671 : : cmd23, 1);
672 : :
673 : : dptr += l2_len - ROC_ONF_IPSEC_OUTB_MAX_L2_INFO_SZ -
674 : : (sizeof(struct roc_ie_on_outb_hdr) - ROC_IE_ON_MAX_IV_LEN);
675 : : ucode_cmd[1] = dptr;
676 : : ucode_cmd[2] = dptr;
677 : :
678 : : /* Update l2 sz */
679 : : *(uint16_t *)(dptr + (sizeof(struct roc_ie_on_outb_hdr) -
680 : : ROC_IE_ON_MAX_IV_LEN)) =
681 : : rte_cpu_to_be_16(ROC_ONF_IPSEC_OUTB_MAX_L2_INFO_SZ);
682 : :
683 : : /* Head wait if needed */
684 : : if (base)
685 : : roc_sso_hws_head_wait(base);
686 : :
687 : : /* ESN */
688 : : outb_priv = roc_nix_inl_on_ipsec_outb_sa_sw_rsvd((void *)sa);
689 : : esn = outb_priv->esn;
690 : : outb_priv->esn = esn + 1;
691 : :
692 : : esn_lo = rte_cpu_to_be_32(esn & (BIT_ULL(32) - 1));
693 : : esn_hi = rte_cpu_to_be_32(esn >> 32);
694 : :
695 : : /* Update ESN, IPID and IV */
696 : : hdr = (struct roc_ie_on_outb_hdr *)dptr;
697 : : hdr->ip_id = esn_lo;
698 : : hdr->seq = esn_lo;
699 : : hdr->esn = esn_hi;
700 : : hdr->df_tos = 0;
701 : :
702 : : rte_io_wmb();
703 : : cn9k_sso_txq_fc_wait(txq);
704 : : cn9k_nix_sec_fc_wait_one(txq);
705 : :
706 : : /* Write CPT instruction to lmt line */
707 : : vst1q_u64(lmt_addr, cmd01);
708 : : vst1q_u64(lmt_addr + 2, cmd23);
709 : :
710 : : roc_lmt_mov_seg(lmt_addr + 4, ucode_cmd, 2);
711 : :
712 : : if (roc_lmt_submit_ldeor(io_addr) == 0) {
713 : : do {
714 : : vst1q_u64(lmt_addr, cmd01);
715 : : vst1q_u64(lmt_addr + 2, cmd23);
716 : : roc_lmt_mov_seg(lmt_addr + 4, ucode_cmd, 2);
717 : :
718 : : lmt_status = roc_lmt_submit_ldeor(io_addr);
719 : : } while (lmt_status == 0);
720 : : }
721 : : }
722 : : #else
723 : :
724 : : static inline void
725 : : cn9k_sso_hws_xmit_sec_one(const struct cn9k_eth_txq *txq, uint64_t base,
726 : : struct rte_mbuf *m, uint64_t *cmd,
727 : : uint32_t flags)
728 : : {
729 : : RTE_SET_USED(txq);
730 : : RTE_SET_USED(base);
731 : : RTE_SET_USED(m);
732 : : RTE_SET_USED(cmd);
733 : : RTE_SET_USED(flags);
734 : : }
735 : : #endif
736 : :
737 : : static __rte_always_inline int32_t
738 : : cn9k_sso_sq_depth(const struct cn9k_eth_txq *txq)
739 : : {
740 : : int32_t avail = (int32_t)txq->nb_sqb_bufs_adj -
741 : : (int32_t)__atomic_load_n(txq->fc_mem, __ATOMIC_RELAXED);
742 : : return (avail << txq->sqes_per_sqb_log2) - avail;
743 : : }
744 : :
745 : : static __rte_always_inline uint16_t
746 : : cn9k_sso_hws_event_tx(uint64_t base, struct rte_event *ev, uint64_t *cmd,
747 : : uint64_t *txq_data, const uint32_t flags)
748 : : {
749 : : struct rte_mbuf *m = ev->mbuf;
750 : : struct cn9k_eth_txq *txq;
751 : :
752 : : /* Perform header writes before barrier for TSO */
753 : : cn9k_nix_xmit_prepare_tso(m, flags);
754 : : /* Lets commit any changes in the packet here in case when
755 : : * fast free is set as no further changes will be made to mbuf.
756 : : * In case of fast free is not set, both cn9k_nix_prepare_mseg()
757 : : * and cn9k_nix_xmit_prepare() has a barrier after refcnt update.
758 : : */
759 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) &&
760 : : !(flags & NIX_TX_OFFLOAD_SECURITY_F))
761 : : rte_io_wmb();
762 : : txq = cn9k_sso_hws_xtract_meta(m, txq_data);
763 : :
764 : : if (flags & NIX_TX_OFFLOAD_MBUF_NOFF_F && txq->tx_compl.ena)
765 : : handle_tx_completion_pkts(txq, 1);
766 : :
767 : : if (cn9k_sso_sq_depth(txq) <= 0)
768 : : return 0;
769 : : cn9k_nix_tx_skeleton(txq, cmd, flags, 0);
770 : : cn9k_nix_xmit_prepare(txq, m, cmd, flags, txq->lso_tun_fmt, txq->mark_flag,
771 : : txq->mark_fmt);
772 : :
773 : : if (flags & NIX_TX_OFFLOAD_SECURITY_F) {
774 : : uint64_t ol_flags = m->ol_flags;
775 : :
776 : : if (ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) {
777 : : uintptr_t ssow_base = base;
778 : :
779 : : if (ev->sched_type)
780 : : ssow_base = 0;
781 : :
782 : : cn9k_sso_hws_xmit_sec_one(txq, ssow_base, m, cmd,
783 : : flags);
784 : : goto done;
785 : : }
786 : :
787 : : if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
788 : : rte_io_wmb();
789 : : }
790 : :
791 : : if (flags & NIX_TX_MULTI_SEG_F) {
792 : : const uint16_t segdw = cn9k_nix_prepare_mseg(txq, m, cmd, flags);
793 : : cn9k_nix_xmit_prepare_tstamp(txq, cmd, m->ol_flags, segdw,
794 : : flags);
795 : : if (!CNXK_TT_FROM_EVENT(ev->event)) {
796 : : cn9k_nix_xmit_mseg_prep_lmt(cmd, txq->lmt_addr, segdw);
797 : : roc_sso_hws_head_wait(base);
798 : : cn9k_sso_txq_fc_wait(txq);
799 : : if (cn9k_nix_xmit_submit_lmt(txq->io_addr) == 0)
800 : : cn9k_nix_xmit_mseg_one(cmd, txq->lmt_addr,
801 : : txq->io_addr, segdw);
802 : : } else {
803 : : cn9k_nix_xmit_mseg_one(cmd, txq->lmt_addr, txq->io_addr,
804 : : segdw);
805 : : }
806 : : } else {
807 : : cn9k_nix_xmit_prepare_tstamp(txq, cmd, m->ol_flags, 4, flags);
808 : : if (!CNXK_TT_FROM_EVENT(ev->event)) {
809 : : cn9k_nix_xmit_prep_lmt(cmd, txq->lmt_addr, flags);
810 : : roc_sso_hws_head_wait(base);
811 : : cn9k_sso_txq_fc_wait(txq);
812 : : if (cn9k_nix_xmit_submit_lmt(txq->io_addr) == 0)
813 : : cn9k_nix_xmit_one(cmd, txq->lmt_addr,
814 : : txq->io_addr, flags);
815 : : } else {
816 : : cn9k_nix_xmit_one(cmd, txq->lmt_addr, txq->io_addr,
817 : : flags);
818 : : }
819 : : }
820 : :
821 : : done:
822 : : return 1;
823 : : }
824 : :
825 : : #define T(name, sz, flags) \
826 : : uint16_t __rte_hot cn9k_sso_hws_tx_adptr_enq_##name( \
827 : : void *port, struct rte_event ev[], uint16_t nb_events); \
828 : : uint16_t __rte_hot cn9k_sso_hws_tx_adptr_enq_seg_##name( \
829 : : void *port, struct rte_event ev[], uint16_t nb_events); \
830 : : uint16_t __rte_hot cn9k_sso_hws_dual_tx_adptr_enq_##name( \
831 : : void *port, struct rte_event ev[], uint16_t nb_events); \
832 : : uint16_t __rte_hot cn9k_sso_hws_dual_tx_adptr_enq_seg_##name( \
833 : : void *port, struct rte_event ev[], uint16_t nb_events);
834 : :
835 : : NIX_TX_FASTPATH_MODES
836 : : #undef T
837 : :
838 : : #define SSO_TX(fn, sz, flags) \
839 : : uint16_t __rte_hot fn(void *port, struct rte_event ev[], \
840 : : uint16_t nb_events) \
841 : : { \
842 : : struct cn9k_sso_hws *ws = port; \
843 : : uint64_t cmd[sz]; \
844 : : RTE_SET_USED(nb_events); \
845 : : return cn9k_sso_hws_event_tx(ws->base, &ev[0], cmd, \
846 : : (uint64_t *)ws->tx_adptr_data, \
847 : : flags); \
848 : : }
849 : :
850 : : #define SSO_TX_SEG(fn, sz, flags) \
851 : : uint16_t __rte_hot fn(void *port, struct rte_event ev[], \
852 : : uint16_t nb_events) \
853 : : { \
854 : : uint64_t cmd[(sz) + CNXK_NIX_TX_MSEG_SG_DWORDS - 2]; \
855 : : struct cn9k_sso_hws *ws = port; \
856 : : RTE_SET_USED(nb_events); \
857 : : return cn9k_sso_hws_event_tx(ws->base, &ev[0], cmd, \
858 : : (uint64_t *)ws->tx_adptr_data, \
859 : : (flags) | NIX_TX_MULTI_SEG_F); \
860 : : }
861 : :
862 : : #define SSO_DUAL_TX(fn, sz, flags) \
863 : : uint16_t __rte_hot fn(void *port, struct rte_event ev[], \
864 : : uint16_t nb_events) \
865 : : { \
866 : : struct cn9k_sso_hws_dual *ws = port; \
867 : : uint64_t cmd[sz]; \
868 : : RTE_SET_USED(nb_events); \
869 : : return cn9k_sso_hws_event_tx(ws->base[!ws->vws], &ev[0], cmd, \
870 : : (uint64_t *)ws->tx_adptr_data, \
871 : : flags); \
872 : : }
873 : :
874 : : #define SSO_DUAL_TX_SEG(fn, sz, flags) \
875 : : uint16_t __rte_hot fn(void *port, struct rte_event ev[], \
876 : : uint16_t nb_events) \
877 : : { \
878 : : uint64_t cmd[(sz) + CNXK_NIX_TX_MSEG_SG_DWORDS - 2]; \
879 : : struct cn9k_sso_hws_dual *ws = port; \
880 : : RTE_SET_USED(nb_events); \
881 : : return cn9k_sso_hws_event_tx(ws->base[!ws->vws], &ev[0], cmd, \
882 : : (uint64_t *)ws->tx_adptr_data, \
883 : : (flags) | NIX_TX_MULTI_SEG_F); \
884 : : }
885 : :
886 : : #endif
|