Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include "cnxk_tim_evdev.h"
6 : : #include "cnxk_tim_worker.h"
7 : :
8 : : static inline int
9 : : cnxk_tim_arm_checks(const struct cnxk_tim_ring *const tim_ring,
10 : : struct rte_event_timer *const tim)
11 : : {
12 : 0 : if (unlikely(tim->state)) {
13 : 0 : tim->state = RTE_EVENT_TIMER_ERROR;
14 : 0 : rte_errno = EALREADY;
15 : 0 : goto fail;
16 : : }
17 : :
18 [ # # # # : 0 : if (unlikely(!tim->timeout_ticks ||
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
19 : : tim->timeout_ticks > tim_ring->nb_bkts)) {
20 : 0 : tim->state = tim->timeout_ticks ?
21 [ # # # # : 0 : RTE_EVENT_TIMER_ERROR_TOOLATE :
# # # # #
# # # # #
# # ]
22 : : RTE_EVENT_TIMER_ERROR_TOOEARLY;
23 : 0 : rte_errno = EINVAL;
24 : 0 : goto fail;
25 : : }
26 : :
27 : : return 0;
28 : :
29 : : fail:
30 : : return -EINVAL;
31 : : }
32 : :
33 : : static inline void
34 : : cnxk_tim_format_event(const struct rte_event_timer *const tim,
35 : : struct cnxk_tim_ent *const entry)
36 : : {
37 : 0 : entry->w0 = (tim->ev.event & 0xFFC000000000) >> 6 |
38 : 0 : (tim->ev.event & 0xFFFFFFFFF);
39 : 0 : entry->wqe = tim->ev.u64;
40 : : }
41 : :
42 : : static __rte_always_inline uint16_t
43 : : cnxk_tim_timer_arm_burst(const struct rte_event_timer_adapter *adptr,
44 : : struct rte_event_timer **tim, const uint16_t nb_timers,
45 : : const uint8_t flags)
46 : : {
47 : 0 : struct cnxk_tim_ring *tim_ring = adptr->data->adapter_priv;
48 : : struct cnxk_tim_ent entry;
49 : : uint16_t index;
50 : : int ret = 0;
51 : :
52 [ # # # # : 0 : for (index = 0; index < nb_timers; index++) {
# # # # #
# # # # #
# # ]
53 [ # # # # : 0 : if (cnxk_tim_arm_checks(tim_ring, tim[index]))
# # # # #
# # # # #
# # ]
54 : : break;
55 : :
56 : : cnxk_tim_format_event(tim[index], &entry);
57 : : if (flags & CNXK_TIM_SP)
58 : : ret = cnxk_tim_add_entry_sp(tim_ring,
59 : : tim[index]->timeout_ticks,
60 : : tim[index], &entry, flags);
61 : : if (flags & CNXK_TIM_MP)
62 : : ret = cnxk_tim_add_entry_mp(tim_ring,
63 : : tim[index]->timeout_ticks,
64 : : tim[index], &entry, flags);
65 : :
66 [ # # # # : 0 : if (unlikely(ret)) {
# # # # #
# # # # #
# # ]
67 : 0 : rte_errno = -ret;
68 : 0 : break;
69 : : }
70 : : }
71 : :
72 : : if (flags & CNXK_TIM_ENA_STATS)
73 : 0 : __atomic_fetch_add(&tim_ring->arm_cnt, index, __ATOMIC_RELAXED);
74 : :
75 : : return index;
76 : : }
77 : :
78 : : #define FP(_name, _f3, _f2, _f1, _flags) \
79 : : uint16_t __rte_noinline cnxk_tim_arm_burst_##_name( \
80 : : const struct rte_event_timer_adapter *adptr, \
81 : : struct rte_event_timer **tim, const uint16_t nb_timers) \
82 : : { \
83 : : return cnxk_tim_timer_arm_burst(adptr, tim, nb_timers, \
84 : : _flags); \
85 : : }
86 : 0 : TIM_ARM_FASTPATH_MODES
87 : : #undef FP
88 : :
89 : : static __rte_always_inline uint16_t
90 : : cnxk_tim_timer_arm_tmo_brst(const struct rte_event_timer_adapter *adptr,
91 : : struct rte_event_timer **tim,
92 : : const uint64_t timeout_tick,
93 : : const uint16_t nb_timers, const uint8_t flags)
94 : : {
95 : : struct cnxk_tim_ent entry[CNXK_TIM_MAX_BURST] __rte_cache_aligned;
96 : 0 : struct cnxk_tim_ring *tim_ring = adptr->data->adapter_priv;
97 : : uint16_t set_timers = 0;
98 : : uint16_t arr_idx = 0;
99 : : uint16_t idx;
100 : : int ret;
101 : :
102 [ # # # # : 0 : if (unlikely(!timeout_tick || timeout_tick > tim_ring->nb_bkts)) {
# # # # ]
103 : : const enum rte_event_timer_state state =
104 [ # # # # : 0 : timeout_tick ? RTE_EVENT_TIMER_ERROR_TOOLATE :
# # # # ]
105 : : RTE_EVENT_TIMER_ERROR_TOOEARLY;
106 [ # # # # : 0 : for (idx = 0; idx < nb_timers; idx++)
# # # # ]
107 : 0 : tim[idx]->state = state;
108 : :
109 : 0 : rte_errno = EINVAL;
110 : 0 : return 0;
111 : : }
112 : :
113 [ # # # # : 0 : while (arr_idx < nb_timers) {
# # # # ]
114 [ # # # # : 0 : for (idx = 0; idx < CNXK_TIM_MAX_BURST && (arr_idx < nb_timers);
# # # # ]
115 : 0 : idx++, arr_idx++) {
116 : 0 : cnxk_tim_format_event(tim[arr_idx], &entry[idx]);
117 : : }
118 : 0 : ret = cnxk_tim_add_entry_brst(tim_ring, timeout_tick,
119 : 0 : &tim[set_timers], entry, idx,
120 : : flags);
121 : 0 : set_timers += ret;
122 [ # # # # : 0 : if (ret != idx)
# # # # ]
123 : : break;
124 : : }
125 : :
126 : : if (flags & CNXK_TIM_ENA_STATS)
127 : 0 : __atomic_fetch_add(&tim_ring->arm_cnt, set_timers,
128 : : __ATOMIC_RELAXED);
129 : :
130 : : return set_timers;
131 : : }
132 : :
133 : : #define FP(_name, _f2, _f1, _flags) \
134 : : uint16_t __rte_noinline cnxk_tim_arm_tmo_tick_burst_##_name( \
135 : : const struct rte_event_timer_adapter *adptr, \
136 : : struct rte_event_timer **tim, const uint64_t timeout_tick, \
137 : : const uint16_t nb_timers) \
138 : : { \
139 : : return cnxk_tim_timer_arm_tmo_brst(adptr, tim, timeout_tick, \
140 : : nb_timers, _flags); \
141 : : }
142 [ # # ]: 0 : TIM_ARM_TMO_FASTPATH_MODES
143 : : #undef FP
144 : :
145 : : uint16_t
146 : 0 : cnxk_tim_timer_cancel_burst(const struct rte_event_timer_adapter *adptr,
147 : : struct rte_event_timer **tim,
148 : : const uint16_t nb_timers)
149 : : {
150 : : uint16_t index;
151 : : int ret;
152 : :
153 : : RTE_SET_USED(adptr);
154 : : rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
155 [ # # ]: 0 : for (index = 0; index < nb_timers; index++) {
156 [ # # ]: 0 : if (tim[index]->state == RTE_EVENT_TIMER_CANCELED) {
157 : 0 : rte_errno = EALREADY;
158 : 0 : break;
159 : : }
160 : :
161 [ # # ]: 0 : if (tim[index]->state != RTE_EVENT_TIMER_ARMED) {
162 : 0 : rte_errno = EINVAL;
163 : 0 : break;
164 : : }
165 : 0 : ret = cnxk_tim_rm_entry(tim[index]);
166 [ # # ]: 0 : if (ret) {
167 : 0 : rte_errno = -ret;
168 : 0 : break;
169 : : }
170 : : }
171 : :
172 : 0 : return index;
173 : : }
174 : :
175 : : int
176 : 0 : cnxk_tim_remaining_ticks_get(const struct rte_event_timer_adapter *adapter,
177 : : const struct rte_event_timer *evtim, uint64_t *ticks_remaining)
178 : : {
179 : 0 : struct cnxk_tim_ring *tim_ring = adapter->data->adapter_priv;
180 : : struct cnxk_tim_bkt *bkt, *current_bkt;
181 : : struct cnxk_tim_ent *entry;
182 : : uint64_t bkt_cyc, bucket;
183 : : uint64_t sema;
184 : :
185 [ # # # # ]: 0 : if (evtim->impl_opaque[1] == 0 || evtim->impl_opaque[0] == 0)
186 : : return -ENOENT;
187 : :
188 : 0 : entry = (struct cnxk_tim_ent *)(uintptr_t)evtim->impl_opaque[0];
189 [ # # ]: 0 : if (entry->wqe != evtim->ev.u64)
190 : : return -ENOENT;
191 : :
192 [ # # ]: 0 : if (evtim->state != RTE_EVENT_TIMER_ARMED)
193 : : return -ENOENT;
194 : :
195 : 0 : bkt = (struct cnxk_tim_bkt *)evtim->impl_opaque[1];
196 [ # # ]: 0 : sema = __atomic_load_n(&bkt->w1, rte_memory_order_acquire);
197 [ # # # # ]: 0 : if (cnxk_tim_bkt_get_hbt(sema) || !cnxk_tim_bkt_get_nent(sema))
198 : : return -ENOENT;
199 : :
200 : 0 : bkt_cyc = tim_ring->tick_fn(tim_ring->tbase) - tim_ring->ring_start_cyc;
201 : : bucket = rte_reciprocal_divide_u64(bkt_cyc, &tim_ring->fast_div);
202 : 0 : current_bkt = &tim_ring->bkt[bucket];
203 : :
204 : 0 : *ticks_remaining = RTE_MAX(bkt, current_bkt) - RTE_MIN(bkt, current_bkt);
205 : : /* Assume that the current bucket is yet to expire */
206 : 0 : *ticks_remaining += 1;
207 : 0 : return 0;
208 : : }
|