Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : :
5 : : #ifndef __CN20K_WORKER_H__
6 : : #define __CN20K_WORKER_H__
7 : :
8 : : #include <rte_event_timer_adapter.h>
9 : : #include <rte_eventdev.h>
10 : :
11 : : #include "cn20k_eventdev.h"
12 : : #include "cn20k_rx.h"
13 : : #include "cnxk_worker.h"
14 : :
15 : : /* CN20K Rx event fastpath */
16 : :
17 : : static __rte_always_inline void
18 : : cn20k_wqe_to_mbuf(uint64_t wqe, const uint64_t __mbuf, uint8_t port_id, const uint32_t tag,
19 : : const uint32_t flags, const void *const lookup_mem, uintptr_t cpth,
20 : : uintptr_t sa_base)
21 : : {
22 : : const uint64_t mbuf_init =
23 : : 0x100010000ULL | RTE_PKTMBUF_HEADROOM | (flags & NIX_RX_OFFLOAD_TSTAMP_F ? 8 : 0);
24 : : struct rte_mbuf *mbuf = (struct rte_mbuf *)__mbuf;
25 : :
26 : 0 : cn20k_nix_cqe_to_mbuf((struct nix_cqe_hdr_s *)wqe, tag, (struct rte_mbuf *)mbuf, lookup_mem,
27 : 0 : mbuf_init | ((uint64_t)port_id) << 48, cpth, sa_base, flags);
28 : : }
29 : :
30 : : static void
31 : 0 : cn20k_sso_process_tstamp(uint64_t u64, uint64_t mbuf, struct cnxk_timesync_info *tstamp)
32 : : {
33 : : uint64_t tstamp_ptr;
34 : : uint8_t laptr;
35 : :
36 : 0 : laptr = (uint8_t)*(uint64_t *)(u64 + (CNXK_SSO_WQE_LAYR_PTR * sizeof(uint64_t)));
37 [ # # ]: 0 : if (laptr == sizeof(uint64_t)) {
38 : : /* Extracting tstamp, if PTP enabled*/
39 : 0 : tstamp_ptr = *(uint64_t *)(((struct nix_wqe_hdr_s *)u64) + CNXK_SSO_WQE_SG_PTR);
40 [ # # ]: 0 : cn20k_nix_mbuf_to_tstamp((struct rte_mbuf *)mbuf, tstamp, true,
41 : : (uint64_t *)tstamp_ptr);
42 : : }
43 : 0 : }
44 : :
45 : : static __rte_always_inline void
46 : : cn20k_process_vwqe(uintptr_t vwqe, uint16_t port_id, const uint32_t flags, struct cn20k_sso_hws *ws)
47 : : {
48 : : uint64_t mbuf_init = 0x100010000ULL | RTE_PKTMBUF_HEADROOM;
49 : 0 : struct cnxk_timesync_info *tstamp = ws->tstamp[port_id];
50 : 0 : void *lookup_mem = ws->lookup_mem;
51 : : uintptr_t lbase = ws->lmt_base;
52 : : struct rte_event_vector *vec;
53 : : uint16_t nb_mbufs, non_vec;
54 : : struct rte_mbuf **wqe;
55 : : struct rte_mbuf *mbuf;
56 : : uint64_t sa_base = 0;
57 : : uintptr_t cpth = 0;
58 : : int i;
59 : :
60 : 0 : mbuf_init |= ((uint64_t)port_id) << 48;
61 : : vec = (struct rte_event_vector *)vwqe;
62 : 0 : wqe = vec->mbufs;
63 : :
64 : 0 : rte_prefetch0(&vec->ptrs[0]);
65 : : #define OBJS_PER_CLINE (RTE_CACHE_LINE_SIZE / sizeof(void *))
66 [ # # # # : 0 : for (i = OBJS_PER_CLINE; i < vec->nb_elem; i += OBJS_PER_CLINE)
# # ]
67 : 0 : rte_prefetch0(&vec->ptrs[i]);
68 : :
69 [ # # # # ]: 0 : if (flags & NIX_RX_OFFLOAD_TSTAMP_F && tstamp)
70 : 0 : mbuf_init |= 8;
71 : :
72 : : nb_mbufs = RTE_ALIGN_FLOOR(vec->nb_elem, NIX_DESCS_PER_LOOP);
73 : : nb_mbufs = cn20k_nix_recv_pkts_vector(&mbuf_init, wqe, nb_mbufs, flags | NIX_RX_VWQE_F,
74 : : lookup_mem, tstamp, lbase, 0);
75 : : wqe += nb_mbufs;
76 : : non_vec = vec->nb_elem - nb_mbufs;
77 : :
78 [ # # # # : 0 : while (non_vec) {
# # ]
79 : 0 : struct nix_cqe_hdr_s *cqe = (struct nix_cqe_hdr_s *)wqe[0];
80 : :
81 : 0 : mbuf = (struct rte_mbuf *)((char *)cqe - sizeof(struct rte_mbuf));
82 : :
83 : : /* Mark mempool obj as "get" as it is alloc'ed by NIX */
84 : : RTE_MEMPOOL_CHECK_COOKIES(mbuf->pool, (void **)&mbuf, 1, 1);
85 : :
86 [ # # # # ]: 0 : cn20k_nix_cqe_to_mbuf(cqe, cqe->tag, mbuf, lookup_mem, mbuf_init, cpth, sa_base,
87 : : flags);
88 : :
89 : : if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
90 : 0 : cn20k_sso_process_tstamp((uint64_t)wqe[0], (uint64_t)mbuf, tstamp);
91 : 0 : wqe[0] = (struct rte_mbuf *)mbuf;
92 : 0 : non_vec--;
93 : 0 : wqe++;
94 : : }
95 : : }
96 : :
97 : : static __rte_always_inline void
98 : : cn20k_sso_hws_post_process(struct cn20k_sso_hws *ws, uint64_t *u64, const uint32_t flags)
99 : : {
100 : : uintptr_t sa_base = 0;
101 : :
102 : 0 : u64[0] = (u64[0] & (0x3ull << 32)) << 6 | (u64[0] & (0x3FFull << 36)) << 4 |
103 : 0 : (u64[0] & 0xffffffff);
104 [ # # # # : 0 : if (CNXK_EVENT_TYPE_FROM_TAG(u64[0]) == RTE_EVENT_TYPE_ETHDEV) {
# # ]
105 : 0 : uint8_t port = CNXK_SUB_EVENT_FROM_TAG(u64[0]);
106 : : uintptr_t cpth = 0;
107 : : uint64_t mbuf;
108 : :
109 : 0 : mbuf = u64[1] - sizeof(struct rte_mbuf);
110 : 0 : rte_prefetch0((void *)mbuf);
111 : :
112 : : /* Mark mempool obj as "get" as it is alloc'ed by NIX */
113 : : RTE_MEMPOOL_CHECK_COOKIES(((struct rte_mbuf *)mbuf)->pool, (void **)&mbuf, 1, 1);
114 : :
115 : 0 : u64[0] = CNXK_CLR_SUB_EVENT(u64[0]);
116 [ # # # # ]: 0 : cn20k_wqe_to_mbuf(u64[1], mbuf, port, u64[0] & 0xFFFFF, flags, ws->lookup_mem, cpth,
117 : : sa_base);
118 : : if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
119 : 0 : cn20k_sso_process_tstamp(u64[1], mbuf, ws->tstamp[port]);
120 : : u64[1] = mbuf;
121 [ # # # # : 0 : } else if (CNXK_EVENT_TYPE_FROM_TAG(u64[0]) == RTE_EVENT_TYPE_ETHDEV_VECTOR) {
# # ]
122 : 0 : uint8_t port = CNXK_SUB_EVENT_FROM_TAG(u64[0]);
123 : 0 : __uint128_t vwqe_hdr = *(__uint128_t *)u64[1];
124 : :
125 : 0 : vwqe_hdr = ((vwqe_hdr >> 64) & 0xFFF) | BIT_ULL(31) | ((vwqe_hdr & 0xFFFF) << 48) |
126 : 0 : ((uint64_t)port << 32);
127 : 0 : *(uint64_t *)u64[1] = (uint64_t)vwqe_hdr;
128 : : cn20k_process_vwqe(u64[1], port, flags, ws);
129 : : /* Mark vector mempool object as get */
130 : : RTE_MEMPOOL_CHECK_COOKIES(rte_mempool_from_obj((void *)u64[1]), (void **)&u64[1], 1,
131 : : 1);
132 [ # # # # : 0 : } else if (CNXK_EVENT_TYPE_FROM_TAG(u64[0]) == RTE_EVENT_TYPE_TIMER) {
# # ]
133 : 0 : struct rte_event_timer *tev = (struct rte_event_timer *)u64[1];
134 : :
135 : 0 : tev->state = RTE_EVENT_TIMER_NOT_ARMED;
136 : 0 : u64[1] = tev->ev.u64;
137 : : }
138 : : }
139 : :
140 : : static __rte_always_inline uint16_t
141 : : cn20k_sso_hws_get_work(struct cn20k_sso_hws *ws, struct rte_event *ev, const uint32_t flags)
142 : : {
143 : : union {
144 : : __uint128_t get_work;
145 : : uint64_t u64[2];
146 : : } gw;
147 : :
148 : : gw.get_work = ws->gw_wdata;
149 : : #if defined(RTE_ARCH_ARM64)
150 : : #if defined(__clang__)
151 : : register uint64_t x0 __asm("x0") = (uint64_t)gw.u64[0];
152 : : register uint64_t x1 __asm("x1") = (uint64_t)gw.u64[1];
153 : : #if defined(RTE_ARM_USE_WFE)
154 : : plt_write64(gw.u64[0], ws->base + SSOW_LF_GWS_OP_GET_WORK0);
155 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
156 : : " ldp %[x0], %[x1], [%[tag_loc]] \n"
157 : : " tbz %[x0], %[pend_gw], done%= \n"
158 : : " sevl \n"
159 : : "rty%=: wfe \n"
160 : : " ldp %[x0], %[x1], [%[tag_loc]] \n"
161 : : " tbnz %[x0], %[pend_gw], rty%= \n"
162 : : "done%=: \n"
163 : : " dmb ld \n"
164 : : : [x0] "+r" (x0), [x1] "+r" (x1)
165 : : : [tag_loc] "r"(ws->base + SSOW_LF_GWS_WQE0),
166 : : [pend_gw] "i"(SSOW_LF_GWS_TAG_PEND_GET_WORK_BIT)
167 : : : "memory");
168 : : #else
169 : : asm volatile(".arch armv8-a+lse\n"
170 : : "caspal %[x0], %[x1], %[x0], %[x1], [%[dst]]\n"
171 : : : [x0] "+r" (x0), [x1] "+r" (x1)
172 : : : [dst] "r"(ws->base + SSOW_LF_GWS_OP_GET_WORK0)
173 : : : "memory");
174 : : #endif
175 : : gw.u64[0] = x0;
176 : : gw.u64[1] = x1;
177 : : #else
178 : : #if defined(RTE_ARM_USE_WFE)
179 : : plt_write64(gw.u64[0], ws->base + SSOW_LF_GWS_OP_GET_WORK0);
180 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
181 : : " ldp %[wdata], %H[wdata], [%[tag_loc]] \n"
182 : : " tbz %[wdata], %[pend_gw], done%= \n"
183 : : " sevl \n"
184 : : "rty%=: wfe \n"
185 : : " ldp %[wdata], %H[wdata], [%[tag_loc]] \n"
186 : : " tbnz %[wdata], %[pend_gw], rty%= \n"
187 : : "done%=: \n"
188 : : " dmb ld \n"
189 : : : [wdata] "=&r"(gw.get_work)
190 : : : [tag_loc] "r"(ws->base + SSOW_LF_GWS_WQE0),
191 : : [pend_gw] "i"(SSOW_LF_GWS_TAG_PEND_GET_WORK_BIT)
192 : : : "memory");
193 : : #else
194 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
195 : : "caspal %[wdata], %H[wdata], %[wdata], %H[wdata], [%[gw_loc]]\n"
196 : : : [wdata] "+r"(gw.get_work)
197 : : : [gw_loc] "r"(ws->base + SSOW_LF_GWS_OP_GET_WORK0)
198 : : : "memory");
199 : : #endif
200 : : #endif
201 : : #else
202 : : plt_write64(gw.u64[0], ws->base + SSOW_LF_GWS_OP_GET_WORK0);
203 : : do {
204 : : roc_load_pair(gw.u64[0], gw.u64[1], ws->base + SSOW_LF_GWS_WQE0);
205 : : } while (gw.u64[0] & BIT_ULL(63));
206 : : rte_atomic_thread_fence(rte_memory_order_seq_cst);
207 : : #endif
208 : : ws->gw_rdata = gw.u64[0];
209 : : if (gw.u64[1])
210 : : cn20k_sso_hws_post_process(ws, gw.u64, flags);
211 : :
212 : : ev->event = gw.u64[0];
213 : : ev->u64 = gw.u64[1];
214 : :
215 : : return !!gw.u64[1];
216 : : }
217 : :
218 : : /* Used in cleaning up workslot. */
219 : : static __rte_always_inline uint16_t
220 : : cn20k_sso_hws_get_work_empty(struct cn20k_sso_hws *ws, struct rte_event *ev, const uint32_t flags)
221 : : {
222 : : union {
223 : : __uint128_t get_work;
224 : : uint64_t u64[2];
225 : : } gw;
226 : :
227 : : #ifdef RTE_ARCH_ARM64
228 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
229 : : " ldp %[tag], %[wqp], [%[tag_loc]] \n"
230 : : " tbz %[tag], 63, .Ldone%= \n"
231 : : " sevl \n"
232 : : ".Lrty%=: wfe \n"
233 : : " ldp %[tag], %[wqp], [%[tag_loc]] \n"
234 : : " tbnz %[tag], 63, .Lrty%= \n"
235 : : ".Ldone%=: dmb ld \n"
236 : : : [tag] "=&r"(gw.u64[0]), [wqp] "=&r"(gw.u64[1])
237 : : : [tag_loc] "r"(ws->base + SSOW_LF_GWS_WQE0)
238 : : : "memory");
239 : : #else
240 : : do {
241 [ # # # # : 0 : roc_load_pair(gw.u64[0], gw.u64[1], ws->base + SSOW_LF_GWS_WQE0);
# # ]
242 [ # # # # : 0 : } while (gw.u64[0] & BIT_ULL(63));
# # ]
243 : : #endif
244 : :
245 : 0 : ws->gw_rdata = gw.u64[0];
246 [ # # # # : 0 : if (gw.u64[1])
# # ]
247 : : cn20k_sso_hws_post_process(ws, gw.u64, flags);
248 : : else
249 : 0 : gw.u64[0] = (gw.u64[0] & (0x3ull << 32)) << 6 |
250 : 0 : (gw.u64[0] & (0x3FFull << 36)) << 4 | (gw.u64[0] & 0xffffffff);
251 : :
252 [ # # # # ]: 0 : ev->event = gw.u64[0];
253 : : ev->u64 = gw.u64[1];
254 : :
255 : : return !!gw.u64[1];
256 : : }
257 : :
258 : : /* CN20K Fastpath functions. */
259 : : uint16_t __rte_hot cn20k_sso_hws_enq_burst(void *port, const struct rte_event ev[],
260 : : uint16_t nb_events);
261 : : uint16_t __rte_hot cn20k_sso_hws_enq_new_burst(void *port, const struct rte_event ev[],
262 : : uint16_t nb_events);
263 : : uint16_t __rte_hot cn20k_sso_hws_enq_fwd_burst(void *port, const struct rte_event ev[],
264 : : uint16_t nb_events);
265 : : int __rte_hot cn20k_sso_hws_profile_switch(void *port, uint8_t profile);
266 : : int __rte_hot cn20k_sso_hws_preschedule_modify(void *port,
267 : : enum rte_event_dev_preschedule_type type);
268 : : void __rte_hot cn20k_sso_hws_preschedule(void *port, enum rte_event_dev_preschedule_type type);
269 : :
270 : : #define R(name, flags) \
271 : : uint16_t __rte_hot cn20k_sso_hws_deq_burst_##name( \
272 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
273 : : uint16_t __rte_hot cn20k_sso_hws_deq_tmo_burst_##name( \
274 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
275 : : uint16_t __rte_hot cn20k_sso_hws_deq_ca_burst_##name( \
276 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
277 : : uint16_t __rte_hot cn20k_sso_hws_deq_tmo_ca_burst_##name( \
278 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
279 : : uint16_t __rte_hot cn20k_sso_hws_deq_seg_burst_##name( \
280 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
281 : : uint16_t __rte_hot cn20k_sso_hws_deq_tmo_seg_burst_##name( \
282 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
283 : : uint16_t __rte_hot cn20k_sso_hws_deq_ca_seg_burst_##name( \
284 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
285 : : uint16_t __rte_hot cn20k_sso_hws_deq_tmo_ca_seg_burst_##name( \
286 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
287 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_burst_##name( \
288 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
289 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_tmo_burst_##name( \
290 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
291 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_ca_burst_##name( \
292 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
293 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_tmo_ca_burst_##name( \
294 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
295 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_seg_burst_##name( \
296 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
297 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_tmo_seg_burst_##name( \
298 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
299 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_ca_seg_burst_##name( \
300 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks); \
301 : : uint16_t __rte_hot cn20k_sso_hws_reas_deq_tmo_ca_seg_burst_##name( \
302 : : void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks);
303 : :
304 : : NIX_RX_FASTPATH_MODES
305 : : #undef R
306 : :
307 : : #define SSO_DEQ(fn, flags) \
308 : : static __rte_always_inline uint16_t fn(void *port, struct rte_event *ev, \
309 : : uint64_t timeout_ticks) \
310 : : { \
311 : : struct cn20k_sso_hws *ws = port; \
312 : : RTE_SET_USED(timeout_ticks); \
313 : : if (ws->swtag_req) { \
314 : : ws->swtag_req = 0; \
315 : : ws->gw_rdata = cnxk_sso_hws_swtag_wait(ws->base + SSOW_LF_GWS_WQE0); \
316 : : return 1; \
317 : : } \
318 : : return cn20k_sso_hws_get_work(ws, ev, flags); \
319 : : }
320 : :
321 : : #define SSO_DEQ_SEG(fn, flags) SSO_DEQ(fn, flags | NIX_RX_MULTI_SEG_F)
322 : :
323 : : #define SSO_DEQ_TMO(fn, flags) \
324 : : static __rte_always_inline uint16_t fn(void *port, struct rte_event *ev, \
325 : : uint64_t timeout_ticks) \
326 : : { \
327 : : struct cn20k_sso_hws *ws = port; \
328 : : uint16_t ret = 1; \
329 : : uint64_t iter; \
330 : : if (ws->swtag_req) { \
331 : : ws->swtag_req = 0; \
332 : : ws->gw_rdata = cnxk_sso_hws_swtag_wait(ws->base + SSOW_LF_GWS_WQE0); \
333 : : return ret; \
334 : : } \
335 : : ret = cn20k_sso_hws_get_work(ws, ev, flags); \
336 : : for (iter = 1; iter < timeout_ticks && (ret == 0); iter++) \
337 : : ret = cn20k_sso_hws_get_work(ws, ev, flags); \
338 : : return ret; \
339 : : }
340 : :
341 : : #define SSO_DEQ_TMO_SEG(fn, flags) SSO_DEQ_TMO(fn, flags | NIX_RX_MULTI_SEG_F)
342 : :
343 : : #define R(name, flags) \
344 : : SSO_DEQ(cn20k_sso_hws_deq_##name, flags) \
345 : : SSO_DEQ(cn20k_sso_hws_reas_deq_##name, flags | NIX_RX_REAS_F) \
346 : : SSO_DEQ_SEG(cn20k_sso_hws_deq_seg_##name, flags) \
347 : : SSO_DEQ_SEG(cn20k_sso_hws_reas_deq_seg_##name, flags | NIX_RX_REAS_F) \
348 : : SSO_DEQ_TMO(cn20k_sso_hws_deq_tmo_##name, flags) \
349 : : SSO_DEQ_TMO(cn20k_sso_hws_reas_deq_tmo_##name, flags | NIX_RX_REAS_F) \
350 : : SSO_DEQ_TMO_SEG(cn20k_sso_hws_deq_tmo_seg_##name, flags) \
351 : : SSO_DEQ_TMO_SEG(cn20k_sso_hws_reas_deq_tmo_seg_##name, flags | NIX_RX_REAS_F)
352 : :
353 : : NIX_RX_FASTPATH_MODES
354 : : #undef R
355 : :
356 : : #define SSO_CMN_DEQ_BURST(fnb, fn, flags) \
357 : : uint16_t __rte_hot fnb(void *port, struct rte_event ev[], uint16_t nb_events, \
358 : : uint64_t timeout_ticks) \
359 : : { \
360 : : RTE_SET_USED(nb_events); \
361 : : return fn(port, ev, timeout_ticks); \
362 : : }
363 : :
364 : : #define SSO_CMN_DEQ_SEG_BURST(fnb, fn, flags) \
365 : : uint16_t __rte_hot fnb(void *port, struct rte_event ev[], uint16_t nb_events, \
366 : : uint64_t timeout_ticks) \
367 : : { \
368 : : RTE_SET_USED(nb_events); \
369 : : return fn(port, ev, timeout_ticks); \
370 : : }
371 : :
372 : : uint16_t __rte_hot cn20k_sso_hws_deq_burst_all_offload(void *port, struct rte_event ev[],
373 : : uint16_t nb_events, uint64_t timeout_ticks);
374 : : uint16_t __rte_hot cn20k_sso_hws_deq_burst_all_offload_tst(void *port, struct rte_event ev[],
375 : : uint16_t nb_events,
376 : : uint64_t timeout_ticks);
377 : :
378 : : #endif
|