Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #ifndef __CNXK_TIM_WORKER_H__
6 : : #define __CNXK_TIM_WORKER_H__
7 : :
8 : : #include "cnxk_tim_evdev.h"
9 : :
10 : : static inline uint8_t
11 : : cnxk_tim_bkt_fetch_lock(uint64_t w1)
12 : : {
13 : 0 : return (w1 >> TIM_BUCKET_W1_S_LOCK) & TIM_BUCKET_W1_M_LOCK;
14 : : }
15 : :
16 : : static inline int16_t
17 : : cnxk_tim_bkt_fetch_rem(uint64_t w1)
18 : : {
19 : 0 : return (w1 >> TIM_BUCKET_W1_S_CHUNK_REMAINDER) &
20 : : TIM_BUCKET_W1_M_CHUNK_REMAINDER;
21 : : }
22 : :
23 : : static inline int16_t
24 : : cnxk_tim_bkt_get_rem(struct cnxk_tim_bkt *bktp)
25 : : {
26 : : return __atomic_load_n(&bktp->chunk_remainder, __ATOMIC_ACQUIRE);
27 : : }
28 : :
29 : : static inline void
30 : : cnxk_tim_bkt_set_rem(struct cnxk_tim_bkt *bktp, uint16_t v)
31 : : {
32 : 0 : __atomic_store_n(&bktp->chunk_remainder, v, __ATOMIC_RELAXED);
33 : : }
34 : :
35 : : static inline void
36 : : cnxk_tim_bkt_sub_rem(struct cnxk_tim_bkt *bktp, uint16_t v)
37 : : {
38 : 0 : __atomic_fetch_sub(&bktp->chunk_remainder, v, __ATOMIC_RELAXED);
39 : : }
40 : :
41 : : static inline uint8_t
42 : : cnxk_tim_bkt_get_hbt(uint64_t w1)
43 : : {
44 [ # # ]: 0 : return (w1 >> TIM_BUCKET_W1_S_HBT) & TIM_BUCKET_W1_M_HBT;
45 : : }
46 : :
47 : : static inline uint8_t
48 : : cnxk_tim_bkt_get_bsk(uint64_t w1)
49 : : {
50 : : return (w1 >> TIM_BUCKET_W1_S_BSK) & TIM_BUCKET_W1_M_BSK;
51 : : }
52 : :
53 : : static inline uint64_t
54 : : cnxk_tim_bkt_clr_bsk(struct cnxk_tim_bkt *bktp)
55 : : {
56 : : /* Clear everything except lock. */
57 : : const uint64_t v = TIM_BUCKET_W1_M_LOCK << TIM_BUCKET_W1_S_LOCK;
58 : :
59 : : return __atomic_fetch_and(&bktp->w1, v, __ATOMIC_ACQ_REL);
60 : : }
61 : :
62 : : static inline uint64_t
63 : : cnxk_tim_bkt_fetch_sema_lock(struct cnxk_tim_bkt *bktp)
64 : : {
65 : 0 : return __atomic_fetch_add(&bktp->w1, TIM_BUCKET_SEMA_WLOCK,
66 : : __ATOMIC_ACQUIRE);
67 : : }
68 : :
69 : : static inline uint64_t
70 : : cnxk_tim_bkt_fetch_sema(struct cnxk_tim_bkt *bktp)
71 : : {
72 : : return __atomic_fetch_add(&bktp->w1, TIM_BUCKET_SEMA, __ATOMIC_RELAXED);
73 : : }
74 : :
75 : : static inline uint64_t
76 : : cnxk_tim_bkt_inc_lock(struct cnxk_tim_bkt *bktp)
77 : : {
78 : : const uint64_t v = 1ull << TIM_BUCKET_W1_S_LOCK;
79 : :
80 : 0 : return __atomic_fetch_add(&bktp->w1, v, __ATOMIC_ACQUIRE);
81 : : }
82 : :
83 : : static inline void
84 : : cnxk_tim_bkt_dec_lock(struct cnxk_tim_bkt *bktp)
85 : : {
86 : 0 : __atomic_fetch_sub(&bktp->lock, 1, __ATOMIC_RELEASE);
87 : 0 : }
88 : :
89 : : static inline void
90 : : cnxk_tim_bkt_dec_lock_relaxed(struct cnxk_tim_bkt *bktp)
91 : : {
92 : 0 : __atomic_fetch_sub(&bktp->lock, 1, __ATOMIC_RELAXED);
93 : 0 : }
94 : :
95 : : static inline uint32_t
96 : : cnxk_tim_bkt_get_nent(uint64_t w1)
97 : : {
98 [ # # ]: 0 : return (w1 >> TIM_BUCKET_W1_S_NUM_ENTRIES) &
99 : : TIM_BUCKET_W1_M_NUM_ENTRIES;
100 : : }
101 : :
102 : : static inline void
103 : : cnxk_tim_bkt_inc_nent(struct cnxk_tim_bkt *bktp)
104 : : {
105 : 0 : __atomic_fetch_add(&bktp->nb_entry, 1, __ATOMIC_RELAXED);
106 : : }
107 : :
108 : : static inline void
109 : : cnxk_tim_bkt_add_nent_relaxed(struct cnxk_tim_bkt *bktp, uint32_t v)
110 : : {
111 : 0 : __atomic_fetch_add(&bktp->nb_entry, v, __ATOMIC_RELAXED);
112 : 0 : }
113 : :
114 : : static inline void
115 : : cnxk_tim_bkt_add_nent(struct cnxk_tim_bkt *bktp, uint32_t v)
116 : : {
117 : 0 : __atomic_fetch_add(&bktp->nb_entry, v, __ATOMIC_RELEASE);
118 : 0 : }
119 : :
120 : : static inline uint64_t
121 : : cnxk_tim_bkt_clr_nent(struct cnxk_tim_bkt *bktp)
122 : : {
123 : : const uint64_t v =
124 : : ~(TIM_BUCKET_W1_M_NUM_ENTRIES << TIM_BUCKET_W1_S_NUM_ENTRIES);
125 : :
126 : : return __atomic_fetch_and(&bktp->w1, v, __ATOMIC_ACQ_REL) & v;
127 : : }
128 : :
129 : : static inline uint64_t
130 : : cnxk_tim_bkt_fast_mod(uint64_t n, uint64_t d, struct rte_reciprocal_u64 R)
131 : : {
132 : 0 : return (n - (d * rte_reciprocal_divide_u64(n, &R)));
133 : : }
134 : :
135 : : static __rte_always_inline void
136 : : cnxk_tim_get_target_bucket(struct cnxk_tim_ring *const tim_ring,
137 : : const uint32_t rel_bkt, struct cnxk_tim_bkt **bkt,
138 : : struct cnxk_tim_bkt **mirr_bkt)
139 : : {
140 : 0 : const uint64_t bkt_cyc =
141 [ # # # # : 0 : tim_ring->tick_fn(tim_ring->tbase) - tim_ring->ring_start_cyc;
# # # # #
# # # # #
# # # # ]
142 : : uint64_t bucket = rte_reciprocal_divide_u64(bkt_cyc, &tim_ring->fast_div);
143 : : uint64_t mirr_bucket = 0;
144 : :
145 [ # # # # : 0 : if ((bkt_cyc - bucket * tim_ring->tck_int) < tim_ring->tck_int / 2)
# # # # #
# # # # #
# # # # ]
146 : 0 : bucket--;
147 : :
148 : 0 : bucket += rel_bkt;
149 [ # # # # : 0 : bucket = cnxk_tim_bkt_fast_mod(bucket, tim_ring->nb_bkts,
# # # # #
# # # # #
# # # # ]
150 : : tim_ring->fast_bkt);
151 : : mirr_bucket =
152 : 0 : cnxk_tim_bkt_fast_mod(bucket + (tim_ring->nb_bkts >> 1),
153 : : tim_ring->nb_bkts, tim_ring->fast_bkt);
154 : 0 : *bkt = &tim_ring->bkt[bucket];
155 : 0 : *mirr_bkt = &tim_ring->bkt[mirr_bucket];
156 : : }
157 : :
158 : : static struct cnxk_tim_ent *
159 : 0 : cnxk_tim_clr_bkt(struct cnxk_tim_ring *const tim_ring,
160 : : struct cnxk_tim_bkt *const bkt)
161 : : {
162 : : #define TIM_MAX_OUTSTANDING_OBJ 64
163 : : void *pend_chunks[TIM_MAX_OUTSTANDING_OBJ];
164 : : struct cnxk_tim_ent *chunk;
165 : : struct cnxk_tim_ent *pnext;
166 : : uint8_t objs = 0;
167 : :
168 : 0 : chunk = ((struct cnxk_tim_ent *)(uintptr_t)bkt->first_chunk);
169 : 0 : chunk = (struct cnxk_tim_ent *)(uintptr_t)(chunk +
170 : 0 : tim_ring->nb_chunk_slots)
171 : 0 : ->w0;
172 [ # # ]: 0 : while (chunk) {
173 : 0 : pnext = (struct cnxk_tim_ent *)(uintptr_t)(
174 : 0 : (chunk + tim_ring->nb_chunk_slots)->w0);
175 [ # # ]: 0 : if (objs == TIM_MAX_OUTSTANDING_OBJ) {
176 [ # # ]: 0 : rte_mempool_put_bulk(tim_ring->chunk_pool, pend_chunks,
177 : : objs);
178 : : objs = 0;
179 : : }
180 : 0 : pend_chunks[objs++] = chunk;
181 : : chunk = pnext;
182 : : }
183 : :
184 [ # # ]: 0 : if (objs)
185 [ # # ]: 0 : rte_mempool_put_bulk(tim_ring->chunk_pool, pend_chunks, objs);
186 : :
187 : 0 : return (struct cnxk_tim_ent *)(uintptr_t)bkt->first_chunk;
188 : : }
189 : :
190 : : static struct cnxk_tim_ent *
191 : 0 : cnxk_tim_refill_chunk(struct cnxk_tim_bkt *const bkt,
192 : : struct cnxk_tim_bkt *const mirr_bkt,
193 : : struct cnxk_tim_ring *const tim_ring)
194 : : {
195 : : struct cnxk_tim_ent *chunk;
196 : :
197 [ # # # # ]: 0 : if (bkt->nb_entry || !bkt->first_chunk) {
198 [ # # # # ]: 0 : if (unlikely(rte_mempool_get(tim_ring->chunk_pool,
199 : : (void **)&chunk)))
200 : : return NULL;
201 [ # # ]: 0 : if (bkt->nb_entry) {
202 : 0 : *(uint64_t *)(((struct cnxk_tim_ent *)
203 : 0 : mirr_bkt->current_chunk) +
204 : 0 : tim_ring->nb_chunk_slots) =
205 : 0 : (uintptr_t)chunk;
206 : : } else {
207 : 0 : bkt->first_chunk = (uintptr_t)chunk;
208 : : }
209 : : } else {
210 : 0 : chunk = cnxk_tim_clr_bkt(tim_ring, bkt);
211 : 0 : bkt->first_chunk = (uintptr_t)chunk;
212 : : }
213 : 0 : *(uint64_t *)(chunk + tim_ring->nb_chunk_slots) = 0;
214 : :
215 : 0 : return chunk;
216 : : }
217 : :
218 : : static struct cnxk_tim_ent *
219 : 0 : cnxk_tim_insert_chunk(struct cnxk_tim_bkt *const bkt,
220 : : struct cnxk_tim_bkt *const mirr_bkt,
221 : : struct cnxk_tim_ring *const tim_ring)
222 : : {
223 : : struct cnxk_tim_ent *chunk;
224 : :
225 [ # # # # ]: 0 : if (unlikely(rte_mempool_get(tim_ring->chunk_pool, (void **)&chunk)))
226 : : return NULL;
227 : :
228 : : RTE_MEMPOOL_CHECK_COOKIES(tim_ring->chunk_pool, (void **)&chunk, 1, 0);
229 : 0 : *(uint64_t *)(chunk + tim_ring->nb_chunk_slots) = 0;
230 [ # # ]: 0 : if (bkt->nb_entry) {
231 : 0 : *(uint64_t *)(((struct cnxk_tim_ent *)(uintptr_t)
232 : 0 : mirr_bkt->current_chunk) +
233 : 0 : tim_ring->nb_chunk_slots) = (uintptr_t)chunk;
234 : : } else {
235 : 0 : bkt->first_chunk = (uintptr_t)chunk;
236 : : }
237 : : return chunk;
238 : : }
239 : :
240 : : static __rte_always_inline int
241 : : cnxk_tim_add_entry_sp(struct cnxk_tim_ring *const tim_ring,
242 : : const uint32_t rel_bkt, struct rte_event_timer *const tim,
243 : : const struct cnxk_tim_ent *const pent,
244 : : const uint8_t flags)
245 : : {
246 : : struct cnxk_tim_ent *chunk = NULL;
247 : : struct cnxk_tim_bkt *mirr_bkt;
248 : : struct cnxk_tim_bkt *bkt;
249 : : uint64_t lock_sema;
250 : : int16_t rem;
251 : :
252 : 0 : __retry:
253 : : cnxk_tim_get_target_bucket(tim_ring, rel_bkt, &bkt, &mirr_bkt);
254 : :
255 : : /* Get Bucket sema*/
256 : : lock_sema = cnxk_tim_bkt_fetch_sema_lock(bkt);
257 : :
258 : : /* Bucket related checks. */
259 [ # # # # : 0 : if (unlikely(cnxk_tim_bkt_get_hbt(lock_sema))) {
# # # # ]
260 [ # # # # : 0 : if (cnxk_tim_bkt_get_nent(lock_sema) != 0) {
# # # # ]
261 : : uint64_t hbt_state;
262 : : #ifdef RTE_ARCH_ARM64
263 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
264 : : " ldxr %[hbt], [%[w1]] \n"
265 : : " tbz %[hbt], 33, .Ldne%= \n"
266 : : " sevl \n"
267 : : ".Lrty%=: wfe \n"
268 : : " ldxr %[hbt], [%[w1]] \n"
269 : : " tbnz %[hbt], 33, .Lrty%=\n"
270 : : ".Ldne%=: \n"
271 : : : [hbt] "=&r"(hbt_state)
272 : : : [w1] "r"((&bkt->w1))
273 : : : "memory");
274 : : #else
275 : : do {
276 : 0 : hbt_state = __atomic_load_n(&bkt->w1,
277 : : __ATOMIC_RELAXED);
278 [ # # # # : 0 : } while (hbt_state & BIT_ULL(33));
# # # # ]
279 : : #endif
280 : :
281 [ # # # # : 0 : if (!(hbt_state & BIT_ULL(34)) ||
# # # # ]
282 [ # # # # : 0 : !(hbt_state & GENMASK(31, 0))) {
# # # # ]
283 : : cnxk_tim_bkt_dec_lock(bkt);
284 : 0 : goto __retry;
285 : : }
286 : : }
287 : : }
288 : : /* Insert the work. */
289 : : rem = cnxk_tim_bkt_fetch_rem(lock_sema);
290 : :
291 [ # # # # : 0 : if (!rem) {
# # # # ]
292 : : if (flags & CNXK_TIM_ENA_FB)
293 : 0 : chunk = cnxk_tim_refill_chunk(bkt, mirr_bkt, tim_ring);
294 : : if (flags & CNXK_TIM_ENA_DFB)
295 : 0 : chunk = cnxk_tim_insert_chunk(bkt, mirr_bkt, tim_ring);
296 : :
297 [ # # # # : 0 : if (unlikely(chunk == NULL)) {
# # # # ]
298 : 0 : bkt->chunk_remainder = 0;
299 : 0 : tim->impl_opaque[0] = 0;
300 : 0 : tim->impl_opaque[1] = 0;
301 : 0 : tim->state = RTE_EVENT_TIMER_ERROR;
302 : : cnxk_tim_bkt_dec_lock(bkt);
303 : : return -ENOMEM;
304 : : }
305 : 0 : mirr_bkt->current_chunk = (uintptr_t)chunk;
306 : 0 : bkt->chunk_remainder = tim_ring->nb_chunk_slots - 1;
307 : : } else {
308 : 0 : chunk = (struct cnxk_tim_ent *)mirr_bkt->current_chunk;
309 : 0 : chunk += tim_ring->nb_chunk_slots - rem;
310 : : }
311 : :
312 : : /* Copy work entry. */
313 : 0 : *chunk = *pent;
314 : :
315 : 0 : tim->impl_opaque[0] = (uintptr_t)chunk;
316 : 0 : tim->impl_opaque[1] = (uintptr_t)bkt;
317 : 0 : rte_atomic_store_explicit(&tim->state, RTE_EVENT_TIMER_ARMED, rte_memory_order_release);
318 : : cnxk_tim_bkt_inc_nent(bkt);
319 : : cnxk_tim_bkt_dec_lock_relaxed(bkt);
320 : :
321 : : return 0;
322 : : }
323 : :
324 : : static __rte_always_inline int
325 : : cnxk_tim_add_entry_mp(struct cnxk_tim_ring *const tim_ring,
326 : : const uint32_t rel_bkt, struct rte_event_timer *const tim,
327 : : const struct cnxk_tim_ent *const pent,
328 : : const uint8_t flags)
329 : : {
330 : : struct cnxk_tim_ent *chunk = NULL;
331 : : struct cnxk_tim_bkt *mirr_bkt;
332 : : struct cnxk_tim_bkt *bkt;
333 : : uint64_t lock_sema;
334 : : int64_t rem;
335 : :
336 : : __retry:
337 : : cnxk_tim_get_target_bucket(tim_ring, rel_bkt, &bkt, &mirr_bkt);
338 : : /* Get Bucket sema*/
339 : : lock_sema = cnxk_tim_bkt_fetch_sema_lock(bkt);
340 : :
341 : : /* Bucket related checks. */
342 [ # # # # : 0 : if (unlikely(cnxk_tim_bkt_get_hbt(lock_sema))) {
# # # # ]
343 [ # # # # : 0 : if (cnxk_tim_bkt_get_nent(lock_sema) != 0) {
# # # # ]
344 : : uint64_t hbt_state;
345 : : #ifdef RTE_ARCH_ARM64
346 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
347 : : " ldxr %[hbt], [%[w1]] \n"
348 : : " tbz %[hbt], 33, .Ldne%= \n"
349 : : " sevl \n"
350 : : ".Lrty%=: wfe \n"
351 : : " ldxr %[hbt], [%[w1]] \n"
352 : : " tbnz %[hbt], 33, .Lrty%=\n"
353 : : ".Ldne%=: \n"
354 : : : [hbt] "=&r"(hbt_state)
355 : : : [w1] "r"((&bkt->w1))
356 : : : "memory");
357 : : #else
358 : : do {
359 : 0 : hbt_state = __atomic_load_n(&bkt->w1,
360 : : __ATOMIC_RELAXED);
361 [ # # # # : 0 : } while (hbt_state & BIT_ULL(33));
# # # # ]
362 : : #endif
363 : :
364 [ # # # # : 0 : if (!(hbt_state & BIT_ULL(34)) ||
# # # # ]
365 [ # # # # : 0 : !(hbt_state & GENMASK(31, 0))) {
# # # # ]
366 : : cnxk_tim_bkt_dec_lock(bkt);
367 : 0 : goto __retry;
368 : : }
369 : : }
370 : : }
371 : :
372 : 0 : rem = cnxk_tim_bkt_fetch_rem(lock_sema);
373 [ # # # # : 0 : if (rem < 0) {
# # # # ]
374 : : cnxk_tim_bkt_dec_lock(bkt);
375 : : #ifdef RTE_ARCH_ARM64
376 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
377 : : " ldxr %[rem], [%[crem]] \n"
378 : : " tbz %[rem], 63, .Ldne%= \n"
379 : : " sevl \n"
380 : : ".Lrty%=: wfe \n"
381 : : " ldxr %[rem], [%[crem]] \n"
382 : : " tbnz %[rem], 63, .Lrty%= \n"
383 : : ".Ldne%=: \n"
384 : : : [rem] "=&r"(rem)
385 : : : [crem] "r"(&bkt->w1)
386 : : : "memory");
387 : : #else
388 [ # # # # : 0 : while (__atomic_load_n((int64_t *)&bkt->w1, __ATOMIC_RELAXED) <
# # # # ]
389 : : 0)
390 : : ;
391 : : #endif
392 : 0 : goto __retry;
393 [ # # # # : 0 : } else if (!rem) {
# # # # ]
394 : : /* Only one thread can be here*/
395 : : if (flags & CNXK_TIM_ENA_FB)
396 : 0 : chunk = cnxk_tim_refill_chunk(bkt, mirr_bkt, tim_ring);
397 : : if (flags & CNXK_TIM_ENA_DFB)
398 : 0 : chunk = cnxk_tim_insert_chunk(bkt, mirr_bkt, tim_ring);
399 : :
400 [ # # # # : 0 : if (unlikely(chunk == NULL)) {
# # # # ]
401 : 0 : tim->impl_opaque[0] = 0;
402 : 0 : tim->impl_opaque[1] = 0;
403 : 0 : tim->state = RTE_EVENT_TIMER_ERROR;
404 : : cnxk_tim_bkt_set_rem(bkt, 0);
405 : : cnxk_tim_bkt_dec_lock(bkt);
406 : : return -ENOMEM;
407 : : }
408 : 0 : *chunk = *pent;
409 [ # # # # : 0 : if (cnxk_tim_bkt_fetch_lock(lock_sema)) {
# # # # ]
410 : : do {
411 : 0 : lock_sema = __atomic_load_n(&bkt->w1,
412 : : __ATOMIC_RELAXED);
413 [ # # # # : 0 : } while (cnxk_tim_bkt_fetch_lock(lock_sema) - 1);
# # # # ]
414 : : }
415 : : rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
416 : 0 : mirr_bkt->current_chunk = (uintptr_t)chunk;
417 : 0 : __atomic_store_n(&bkt->chunk_remainder,
418 : 0 : tim_ring->nb_chunk_slots - 1,
419 : : __ATOMIC_RELEASE);
420 : : } else {
421 : 0 : chunk = (struct cnxk_tim_ent *)mirr_bkt->current_chunk;
422 : 0 : chunk += tim_ring->nb_chunk_slots - rem;
423 : 0 : *chunk = *pent;
424 : : }
425 : :
426 : 0 : tim->impl_opaque[0] = (uintptr_t)chunk;
427 : 0 : tim->impl_opaque[1] = (uintptr_t)bkt;
428 : 0 : rte_atomic_store_explicit(&tim->state, RTE_EVENT_TIMER_ARMED, rte_memory_order_release);
429 : : cnxk_tim_bkt_inc_nent(bkt);
430 : : cnxk_tim_bkt_dec_lock_relaxed(bkt);
431 : :
432 : : return 0;
433 : : }
434 : :
435 : : static inline uint16_t
436 : : cnxk_tim_cpy_wrk(uint16_t index, uint16_t cpy_lmt, struct cnxk_tim_ent *chunk,
437 : : struct rte_event_timer **const tim,
438 : : const struct cnxk_tim_ent *const ents,
439 : : const struct cnxk_tim_bkt *const bkt)
440 : : {
441 [ # # # # : 0 : for (; index < cpy_lmt; index++) {
# # ]
442 : 0 : *chunk = *(ents + index);
443 : 0 : tim[index]->impl_opaque[0] = (uintptr_t)chunk++;
444 : 0 : tim[index]->impl_opaque[1] = (uintptr_t)bkt;
445 : 0 : tim[index]->state = RTE_EVENT_TIMER_ARMED;
446 : : }
447 : :
448 : : return index;
449 : : }
450 : :
451 : : /* Burst mode functions */
452 : : static inline int
453 : 0 : cnxk_tim_add_entry_brst(struct cnxk_tim_ring *const tim_ring,
454 : : const uint16_t rel_bkt,
455 : : struct rte_event_timer **const tim,
456 : : const struct cnxk_tim_ent *ents,
457 : : const uint16_t nb_timers, const uint8_t flags)
458 : : {
459 : : struct cnxk_tim_ent *chunk = NULL;
460 : : struct cnxk_tim_bkt *mirr_bkt;
461 : : struct cnxk_tim_bkt *bkt;
462 : : int16_t chunk_remainder;
463 : : uint16_t index = 0;
464 : : uint64_t lock_sema;
465 : : int16_t rem;
466 : : uint8_t lock_cnt;
467 : :
468 : : __retry:
469 : : cnxk_tim_get_target_bucket(tim_ring, rel_bkt, &bkt, &mirr_bkt);
470 : :
471 : : /* Only one thread beyond this. */
472 : : lock_sema = cnxk_tim_bkt_inc_lock(bkt);
473 : :
474 : : /* Bucket related checks. */
475 [ # # ]: 0 : if (unlikely(cnxk_tim_bkt_get_hbt(lock_sema))) {
476 [ # # ]: 0 : if (cnxk_tim_bkt_get_nent(lock_sema) != 0) {
477 : : uint64_t hbt_state;
478 : : #ifdef RTE_ARCH_ARM64
479 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
480 : : " ldxr %[hbt], [%[w1]] \n"
481 : : " tbz %[hbt], 33, .Ldne%= \n"
482 : : " sevl \n"
483 : : ".Lrty%=: wfe \n"
484 : : " ldxr %[hbt], [%[w1]] \n"
485 : : " tbnz %[hbt], 33, .Lrty%=\n"
486 : : ".Ldne%=: \n"
487 : : : [hbt] "=&r"(hbt_state)
488 : : : [w1] "r"((&bkt->w1))
489 : : : "memory");
490 : : #else
491 : : do {
492 : 0 : hbt_state = __atomic_load_n(&bkt->w1,
493 : : __ATOMIC_RELAXED);
494 [ # # ]: 0 : } while (hbt_state & BIT_ULL(33));
495 : : #endif
496 : :
497 [ # # ]: 0 : if (!(hbt_state & BIT_ULL(34)) ||
498 [ # # ]: 0 : !(hbt_state & GENMASK(31, 0))) {
499 : : cnxk_tim_bkt_dec_lock(bkt);
500 : 0 : goto __retry;
501 : : }
502 : : }
503 : : }
504 : :
505 : 0 : lock_cnt = (uint8_t)((lock_sema >> TIM_BUCKET_W1_S_LOCK) &
506 : : TIM_BUCKET_W1_M_LOCK);
507 [ # # ]: 0 : if (lock_cnt) {
508 : : cnxk_tim_bkt_dec_lock(bkt);
509 : : #ifdef RTE_ARCH_ARM64
510 : : asm volatile(PLT_CPU_FEATURE_PREAMBLE
511 : : " ldxrb %w[lock_cnt], [%[lock]] \n"
512 : : " tst %w[lock_cnt], 255 \n"
513 : : " beq .Ldne%= \n"
514 : : " sevl \n"
515 : : ".Lrty%=: wfe \n"
516 : : " ldxrb %w[lock_cnt], [%[lock]] \n"
517 : : " tst %w[lock_cnt], 255 \n"
518 : : " bne .Lrty%= \n"
519 : : ".Ldne%=: \n"
520 : : : [lock_cnt] "=&r"(lock_cnt)
521 : : : [lock] "r"(&bkt->lock)
522 : : : "memory");
523 : : #else
524 [ # # ]: 0 : while (__atomic_load_n(&bkt->lock, __ATOMIC_RELAXED))
525 : : ;
526 : : #endif
527 : 0 : goto __retry;
528 : : }
529 : :
530 : : chunk_remainder = cnxk_tim_bkt_fetch_rem(lock_sema);
531 : 0 : rem = chunk_remainder - nb_timers;
532 [ # # ]: 0 : if (rem < 0) {
533 [ # # ]: 0 : if (chunk_remainder > 0) {
534 : 0 : chunk = ((struct cnxk_tim_ent *)
535 : 0 : mirr_bkt->current_chunk) +
536 : 0 : tim_ring->nb_chunk_slots - chunk_remainder;
537 : :
538 : 0 : index = cnxk_tim_cpy_wrk(index, chunk_remainder, chunk,
539 : : tim, ents, bkt);
540 : : cnxk_tim_bkt_sub_rem(bkt, chunk_remainder);
541 : 0 : cnxk_tim_bkt_add_nent_relaxed(bkt, chunk_remainder);
542 : : }
543 : :
544 [ # # ]: 0 : if (flags & CNXK_TIM_ENA_FB)
545 : 0 : chunk = cnxk_tim_refill_chunk(bkt, mirr_bkt, tim_ring);
546 [ # # ]: 0 : if (flags & CNXK_TIM_ENA_DFB)
547 : 0 : chunk = cnxk_tim_insert_chunk(bkt, mirr_bkt, tim_ring);
548 : :
549 [ # # ]: 0 : if (unlikely(chunk == NULL)) {
550 : : cnxk_tim_bkt_dec_lock_relaxed(bkt);
551 : 0 : rte_errno = ENOMEM;
552 : 0 : tim[index]->state = RTE_EVENT_TIMER_ERROR;
553 : 0 : return index;
554 : : }
555 : 0 : *(uint64_t *)(chunk + tim_ring->nb_chunk_slots) = 0;
556 : 0 : mirr_bkt->current_chunk = (uintptr_t)chunk;
557 : 0 : index = cnxk_tim_cpy_wrk(index, nb_timers, chunk, tim, ents,
558 : : bkt) -
559 : : index;
560 : :
561 : 0 : cnxk_tim_bkt_set_rem(bkt, tim_ring->nb_chunk_slots - index);
562 : 0 : cnxk_tim_bkt_add_nent(bkt, index);
563 : : } else {
564 : 0 : chunk = (struct cnxk_tim_ent *)mirr_bkt->current_chunk;
565 : 0 : chunk += (tim_ring->nb_chunk_slots - chunk_remainder);
566 : :
567 : 0 : cnxk_tim_cpy_wrk(index, nb_timers, chunk, tim, ents, bkt);
568 : : cnxk_tim_bkt_sub_rem(bkt, nb_timers);
569 : 0 : cnxk_tim_bkt_add_nent(bkt, nb_timers);
570 : : }
571 : :
572 : : cnxk_tim_bkt_dec_lock_relaxed(bkt);
573 : :
574 : 0 : return nb_timers;
575 : : }
576 : :
577 : : static int
578 : 0 : cnxk_tim_rm_entry(struct rte_event_timer *tim)
579 : : {
580 : : struct cnxk_tim_ent *entry;
581 : : struct cnxk_tim_bkt *bkt;
582 : : uint64_t lock_sema;
583 : :
584 [ # # # # ]: 0 : if (tim->impl_opaque[1] == 0 || tim->impl_opaque[0] == 0)
585 : : return -ENOENT;
586 : :
587 : 0 : entry = (struct cnxk_tim_ent *)(uintptr_t)tim->impl_opaque[0];
588 [ # # ]: 0 : if (entry->wqe != tim->ev.u64) {
589 : 0 : tim->impl_opaque[0] = 0;
590 : 0 : tim->impl_opaque[1] = 0;
591 : 0 : return -ENOENT;
592 : : }
593 : :
594 : 0 : bkt = (struct cnxk_tim_bkt *)(uintptr_t)tim->impl_opaque[1];
595 : : lock_sema = cnxk_tim_bkt_inc_lock(bkt);
596 [ # # # # ]: 0 : if (cnxk_tim_bkt_get_hbt(lock_sema) ||
597 : : !cnxk_tim_bkt_get_nent(lock_sema)) {
598 : 0 : tim->impl_opaque[0] = 0;
599 : 0 : tim->impl_opaque[1] = 0;
600 : : cnxk_tim_bkt_dec_lock(bkt);
601 : 0 : return -ENOENT;
602 : : }
603 : :
604 : 0 : entry->w0 = 0;
605 : 0 : entry->wqe = 0;
606 : 0 : tim->state = RTE_EVENT_TIMER_CANCELED;
607 : 0 : tim->impl_opaque[0] = 0;
608 : 0 : tim->impl_opaque[1] = 0;
609 : : cnxk_tim_bkt_dec_lock(bkt);
610 : :
611 : 0 : return 0;
612 : : }
613 : :
614 : : #endif /* __CNXK_TIM_WORKER_H__ */
|