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