76#include "em_libconfig.h"
82#include "em_timer_types.h"
85#define TMR_I2H(x) ((em_timer_t)(uintptr_t)((x) + 1))
86#define TMR_H2I(x) ((int)((uintptr_t)(x) - 1))
92ODP_STATIC_ASSERT(
sizeof(
em_fract_u64_t) ==
sizeof(odp_fract_u64_t),
93 "em_fract_u64_t size must match odp_fract_u64_t");
95 offsetof(odp_fract_u64_t, integer),
96 "em_fract_u64_t.integer offset mismatch");
98 offsetof(odp_fract_u64_t, numer),
99 "em_fract_u64_t.numer offset mismatch");
101 offsetof(odp_fract_u64_t, denom),
102 "em_fract_u64_t.denom offset mismatch");
104static inline em_status_t timer_rv_odp2em(
int odpret)
107 case ODP_TIMER_SUCCESS:
109 case ODP_TIMER_TOO_NEAR:
111 case ODP_TIMER_TOO_FAR:
113#if !PRE_1_50_ODP_TIMER_API
124static inline int is_queue_valid_type(em_timer_t tmr,
const queue_elem_t *q_elem)
126 unsigned int tmridx = (
unsigned int)TMR_H2I(tmr);
129 if (
em_shm->timers.timer[tmridx].plain_q_ok &&
164static inline int is_timer_valid(em_timer_t tmr)
172 i = (
unsigned int)TMR_H2I(tmr);
173 if (unlikely(i >= EM_ODP_MAX_TIMERS))
176 if (unlikely(tmrs->timer[i].odp_tmr_pool == ODP_TIMER_POOL_INVALID ||
177 tmrs->timer[i].tmo_pool == ODP_POOL_INVALID))
193 "Invalid event type:%u, expected timer-ring:%u",
198 "Wrong event returned? tmo %p->%p", tmo, ev_hdr->
tmo);
200 int ret = odp_timer_periodic_ack(tmo->odp_timer, odp_ev);
202 if (unlikely(ret < 0))
204 "Tmo ACK: ring timer odp ack fail, rv %d", ret);
206#if PRE_1_50_ODP_TIMER_API
207 if (unlikely(ret == 2)) {
210 atomic_thread_fence(memory_order_release);
211 TMR_DBG_PRINT(
"last periodic event, deleted %p\n", odp_ev);
227 if (unlikely(ret == 1)) {
233 TMR_DBG_PRINT(
"last periodic event %p\n", odp_ev);
243 if (timer->tmo_pool != ODP_POOL_INVALID &&
244 timer->tmo_pool !=
em_shm->timers.shared_tmo_pool)
245 odp_pool_destroy(timer->tmo_pool);
246 if (timer->odp_tmr_pool != ODP_TIMER_POOL_INVALID)
247 odp_timer_pool_destroy(timer->odp_tmr_pool);
248 timer->tmo_pool = ODP_POOL_INVALID;
249 timer->odp_tmr_pool = ODP_TIMER_POOL_INVALID;
250 TMR_DBG_PRINT(
"cleaned up failed timer create\n");
253static odp_pool_t create_tmo_handle_pool(uint32_t num_buf, uint32_t cache,
256 odp_pool_param_t odp_pool_param;
258 char tmo_pool_name[ODP_POOL_NAME_LEN];
260 odp_pool_param_init(&odp_pool_param);
261 odp_pool_param.type = ODP_POOL_BUFFER;
263 odp_pool_param.buf.align = ODP_CACHE_LINE_SIZE;
264 odp_pool_param.buf.cache_size = cache;
265 odp_pool_param.stats.all = 0;
266 TMR_DBG_PRINT(
"tmo handle pool cache %d\n", cache);
268 uint32_t num = num_buf;
277 num += (max_cores - 1) * cache;
280 if (num_buf != num) {
281 TMR_DBG_PRINT(
"Adjusted pool size %d->%d due to local caching (%d)\n",
282 num_buf, num, odp_pool_param.buf.cache_size);
284 odp_pool_param.buf.num = num;
285 snprintf(tmo_pool_name, ODP_POOL_NAME_LEN,
"Tmo-pool-%d", tmr->idx);
286 pool = odp_pool_create(tmo_pool_name, &odp_pool_param);
287 if (pool != ODP_POOL_INVALID) {
288 TMR_DBG_PRINT(
"Created ODP-pool: %s for %d timeouts\n",
289 tmo_pool_name, odp_pool_param.buf.num);
294#if !PRE_1_50_ODP_TIMER_API
299static void ring_tmo_uarea_init(
void *uarea, uint32_t size,
void *args,
300 uint32_t index, uint32_t max_num)
309 ev_hdr->
flags.all = 0;
320#if PRE_1_50_ODP_TIMER_API
321static inline odp_event_t alloc_odp_timeout(
em_tmo_t tmo)
323 odp_timeout_t odp_tmo = odp_timeout_alloc(tmo->ring_tmo_pool);
325 if (unlikely(odp_tmo == ODP_TIMEOUT_INVALID))
326 return ODP_EVENT_INVALID;
329 event_hdr_t *
const ev_hdr = odp_timeout_user_area(odp_tmo);
330 odp_event_t odp_event = odp_timeout_to_event(odp_tmo);
331 em_event_t
event = event_odp2em(odp_event);
333 if (unlikely(!ev_hdr)) {
334 odp_timeout_free(odp_tmo);
335 return ODP_EVENT_INVALID;
339 event = evstate_alloc_tmo(event, ev_hdr);
340 ev_hdr->
flags.all = 0;
352static inline void free_odp_timeout(odp_event_t odp_event)
355 em_event_t
event = event_odp2em(odp_event);
358 event = ev_hdr->
event;
359 evstate_free(event, ev_hdr, EVSTATE__TMO_DELETE);
362 odp_event_free(odp_event);
366static inline em_status_t handle_ack_noskip(em_event_t next_tmo_ev,
371 evstate_usr2em_revert(next_tmo_ev, ev_hdr, EVSTATE__TMO_ACK__NOSKIP);
375 if (unlikely(err !=
EM_OK)) {
376 err =
INTERNAL_ERROR(err, EM_ESCOPE_TMO_ACK,
"Tmo ACK: noskip em_send fail");
384static inline void handle_ack_skip(
em_tmo_t tmo)
386 uint64_t odpt = odp_timer_current_tick(tmo->odp_timer_pool);
389 if (odpt > tmo->last_tick)
390 skips = ((odpt - tmo->last_tick) / tmo->period) + 1;
394 tmo->last_tick += skips * tmo->period;
395 TMR_DBG_PRINT(
"%lu skips * %lu ticks => new tgt %lu\n",
396 skips, tmo->period, tmo->last_tick);
397 if (EM_TIMER_TMO_STATS)
413 if (unlikely(flags & inv_flags))
421 if (unlikely(tmr_attr == NULL)) {
428 "Not initialized: em_timer_attr_init(tmr_attr) not called");
433 "Only res_ns OR res_hz allowed");
439static inline bool check_timer_attr_ring(
const em_timer_attr_t *ring_attr)
441 if (unlikely(ring_attr == NULL)) {
448 "Not initialized: em_timer_ring_attr_init(ring_attr) not called");
461 "Invalid attr values for ring timer");
468static inline bool check_timer_attr_ring_freq(
const em_timer_attr_t *ring_attr)
470 if (unlikely(ring_attr == NULL)) {
477 "Not initialized: em_timer_ring_freq_attr_init() not called");
482 "EM_TIMER_FLAG_RING_FREQ not set");
488 "Invalid freq params: freq_hz=%p, num=%u",
495static inline int find_free_timer_index(
void)
505 for (i = 0; i < EM_ODP_MAX_TIMERS; i++) {
508 if (timer->odp_tmr_pool == ODP_TIMER_POOL_INVALID)
530 odp_timer_clk_src_t odp_clksrc;
531 odp_timer_capability_t odp_capa;
532 odp_timer_res_capability_t odp_res_capa;
538 "Unsupported EM-timer clock source:%d",
542 err = odp_timer_capability(odp_clksrc, &odp_capa);
545 "Timer capability: ret %d, odp-clksrc:%d",
550 TMR_DBG_PRINT(
"odp says highest res %lu\n", odp_capa.highest_res_ns);
551 if (unlikely(odp_capa.highest_res_ns > tmr_attr->
resparam.
res_ns)) {
553 "Timer capability: maxres %lu req %lu, odp-clksrc:%d!",
558 memset(&odp_res_capa, 0,
sizeof(odp_timer_res_capability_t));
560 err = odp_timer_res_capability(odp_clksrc, &odp_res_capa);
563 "Timer res capability failed: ret %d, odp-clksrc:%d, res %lu",
568 TMR_DBG_PRINT(
"res %lu -> ODP says min %lu, max %lu\n",
570 odp_res_capa.max_tmo);
572 tmr_attr->
num_tmo = EM_ODP_DEFAULT_TMOS;
573 if (odp_capa.max_timers && odp_capa.max_timers < EM_ODP_DEFAULT_TMOS)
574 tmr_attr->
num_tmo = odp_capa.max_timers;
578 tmr_attr->
name[0] = 0;
585 em_timer_clksrc_t clk_src,
591 if (unlikely(ring_attr == NULL))
601 ring_attr->
num_tmo = EM_ODP_DEFAULT_RING_TMOS;
603 ring_attr->
name[0] = 0;
607 odp_timer_clk_src_t odp_clksrc;
608 odp_timer_capability_t capa;
613 if (unlikely(odp_timer_capability(odp_clksrc, &capa) != 0)) {
614 TMR_DBG_PRINT(
"odp_timer_capability returned error for clk_src %u\n", odp_clksrc);
618 if (capa.periodic.max_pools == 0)
621 if (capa.periodic.max_timers < ring_attr->
num_tmo)
622 ring_attr->
num_tmo = capa.periodic.max_timers;
624 odp_timer_periodic_capability_t pcapa;
628#if PRE_1_50_ODP_TIMER_API
633 rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
641 pcapa.type = ODP_TIMER_TYPE_PERIODIC_BASE_MUL;
646 rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
662 em_timer_clksrc_t clk_src,
667#if PRE_1_50_ODP_TIMER_API
676 if (unlikely(ring_attr == NULL || freq_hz == NULL || num == 0))
686 ring_attr->
num_tmo = EM_ODP_DEFAULT_RING_TMOS;
688 ring_attr->
name[0] = 0;
692 odp_timer_clk_src_t odp_clksrc;
693 odp_timer_capability_t capa;
694 int rv = timer_clksrc_em2odp(clk_src, &odp_clksrc);
698 if (unlikely(odp_timer_capability(odp_clksrc, &capa) != 0)) {
699 TMR_DBG_PRINT(
"odp_timer_capability returned error for clk_src %u\n", odp_clksrc);
703 if (capa.periodic.max_pools == 0 || !capa.periodic.support.freq)
706 if (capa.periodic.max_timers < ring_attr->
num_tmo)
707 ring_attr->
num_tmo = capa.periodic.max_timers;
709 odp_timer_periodic_capability_t pcapa;
711 pcapa.type = ODP_TIMER_TYPE_PERIODIC_FREQ;
712 pcapa.res_ns = res_ns;
713 pcapa.freq.freq_hz = (odp_fract_u64_t *)freq_hz;
714 pcapa.freq.num = num;
715 rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
730 EM_LOG(EM_LOG_DBG,
"%s(): NULL capa ptr!\n", __func__);
734 odp_timer_clk_src_t odp_clksrc;
735 odp_timer_capability_t odp_capa;
737 if (unlikely(timer_clksrc_em2odp(clk_src, &odp_clksrc) ||
738 odp_timer_capability(odp_clksrc, &odp_capa))) {
739 EM_LOG(EM_LOG_DBG,
"%s: Not supported clk_src %d\n", __func__, clk_src);
743 capa->
max_timers = odp_capa.max_pools < EM_ODP_MAX_TIMERS ?
744 odp_capa.max_pools : EM_ODP_MAX_TIMERS;
768#if PRE_1_50_ODP_TIMER_API
797 EM_LOG(EM_LOG_DBG,
"%s: NULL ptr res\n", __func__);
801 odp_timer_clk_src_t odp_clksrc;
802 odp_timer_res_capability_t odp_res_capa;
805 err = timer_clksrc_em2odp(clk_src, &odp_clksrc);
807 EM_LOG(EM_LOG_DBG,
"%s: Not supported clk_src %d\n", __func__, clk_src);
810 memset(&odp_res_capa, 0,
sizeof(odp_timer_res_capability_t));
811 odp_res_capa.res_ns = res->
res_ns;
812 odp_res_capa.res_hz = res->
res_hz;
813 odp_res_capa.max_tmo = res->
max_tmo;
814 err = odp_timer_res_capability(odp_clksrc, &odp_res_capa);
816 EM_LOG(EM_LOG_DBG,
"%s: ODP res_capability failed (ret %d)!\n", __func__, err);
819 res->
min_tmo = odp_res_capa.min_tmo;
820 res->
max_tmo = odp_res_capa.max_tmo;
821 res->
res_ns = odp_res_capa.res_ns;
822 res->
res_hz = odp_res_capa.res_hz;
829 odp_timer_clk_src_t odp_clksrc;
830 odp_timer_periodic_capability_t pcapa;
833 EM_LOG(EM_LOG_DBG,
"%s: NULL ptr ring\n", __func__);
837 if (unlikely(timer_clksrc_em2odp(ring->
clk_src, &odp_clksrc))) {
838 EM_LOG(EM_LOG_DBG,
"%s: Invalid clk_src %d\n", __func__, ring->
clk_src);
842 pcapa.res_ns = ring->
res_ns;
844#if PRE_1_50_ODP_TIMER_API
848 pcapa.max_multiplier = ring->
max_mul;
849 int rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
854 ring->
max_mul = pcapa.max_multiplier;
856 pcapa.type = ODP_TIMER_TYPE_PERIODIC_BASE_MUL;
858 pcapa.base_mul.base_freq_hz.numer = ring->
base_hz.
numer;
859 pcapa.base_mul.base_freq_hz.denom = ring->
base_hz.
denom;
860 pcapa.base_mul.max_multiplier = ring->
max_mul;
861 int rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
864 ring->
base_hz.
numer = pcapa.base_mul.base_freq_hz.numer;
865 ring->
base_hz.
denom = pcapa.base_mul.base_freq_hz.denom;
866 ring->
max_mul = pcapa.base_mul.max_multiplier;
868 ring->
res_ns = pcapa.res_ns;
870 if (unlikely(rv < 0)) {
871 EM_LOG(EM_LOG_DBG,
"%s: odp failed periodic capability for clk_src %d\n",
883#if PRE_1_50_ODP_TIMER_API
887 odp_timer_clk_src_t odp_clksrc;
888 odp_timer_periodic_capability_t pcapa;
891 EM_LOG(EM_LOG_DBG,
"%s: NULL ptr ring\n", __func__);
896 EM_LOG(EM_LOG_DBG,
"%s: Invalid freq params\n", __func__);
900 if (unlikely(timer_clksrc_em2odp(ring->
clk_src, &odp_clksrc))) {
901 EM_LOG(EM_LOG_DBG,
"%s: Invalid clk_src %d\n", __func__, ring->
clk_src);
905 pcapa.type = ODP_TIMER_TYPE_PERIODIC_FREQ;
906 pcapa.res_ns = ring->
res_ns;
907 pcapa.freq.freq_hz = (odp_fract_u64_t *)ring->
freq_hz;
908 pcapa.freq.num = ring->
num;
910 int rv = odp_timer_periodic_capability(odp_clksrc, &pcapa);
912 ring->
res_ns = pcapa.res_ns;
915 if (unlikely(rv < 0)) {
916 EM_LOG(EM_LOG_DBG,
"%s: odp failed periodic capability for clk_src %d\n",
932 "Timer is not initialized!");
937 if (check_timer_attr(tmr_attr) ==
false)
941 odp_timer_pool_param_t odp_tpool_param;
942 odp_timer_clk_src_t odp_clksrc;
944 odp_timer_pool_param_init(&odp_tpool_param);
949 odp_tpool_param.num_timers = tmr_attr->
num_tmo;
951 if (unlikely(timer_clksrc_em2odp(tmr_attr->
resparam.
clk_src, &odp_clksrc))) {
953 "Unsupported EM-timer clock source:%d",
957 odp_tpool_param.clk_src = odp_clksrc;
960 odp_timer_capability_t capa;
962 if (unlikely(odp_timer_capability(odp_clksrc, &capa))) {
964 "ODP timer capa failed for clk:%d",
968 if (unlikely(!capa.queue_type_sched)) {
970 "ODP does not support scheduled q for clk:%d",
975 if (unlikely(tmr_attr->
priority > capa.max_priority)) {
977 "Priority %u exceeds ODP max %u for clk:%d",
978 tmr_attr->
priority, capa.max_priority,
982 odp_tpool_param.priority = tmr_attr->
priority;
984 odp_ticketlock_lock(&
em_shm->timers.timer_lock);
986 int i = find_free_timer_index();
988 if (unlikely(i >= EM_ODP_MAX_TIMERS)) {
989 odp_ticketlock_unlock(&
em_shm->timers.timer_lock);
991 "No more timers available");
996 char timer_pool_name[ODP_TIMER_POOL_NAME_LEN];
997 const char *name = tmr_attr->
name;
998 const char *reason =
"";
1000 if (tmr_attr->
name[0] ==
'\0') {
1001 snprintf(timer_pool_name, ODP_TIMER_POOL_NAME_LEN,
1002 "EM-timer-%d", timer->idx);
1003 name = timer_pool_name;
1006 TMR_DBG_PRINT(
"Creating ODP tmr pool: clk %d, res_ns %lu, res_hz %lu, priority %u\n",
1007 odp_tpool_param.clk_src, odp_tpool_param.res_ns,
1008 odp_tpool_param.res_hz, odp_tpool_param.priority);
1009 timer->odp_tmr_pool = odp_timer_pool_create(name, &odp_tpool_param);
1010 if (unlikely(timer->odp_tmr_pool == ODP_TIMER_POOL_INVALID)) {
1011 reason =
"odp_timer_pool_create error";
1014 TMR_DBG_PRINT(
"Created timer: %s with idx: %d\n", name, timer->idx);
1017 if (!
em_shm->
opt.timer.shared_tmo_pool_enable) {
1018 odp_pool_t opool = create_tmo_handle_pool(tmr_attr->
num_tmo,
1019 em_shm->
opt.timer.tmo_pool_cache, timer);
1021 if (unlikely(opool == ODP_POOL_INVALID)) {
1022 reason =
"Tmo handle buffer pool create failed";
1026 timer->tmo_pool = opool;
1027 TMR_DBG_PRINT(
"Created per-timer tmo handle pool\n");
1029 if (
em_shm->timers.shared_tmo_pool == ODP_POOL_INVALID) {
1031 create_tmo_handle_pool(
em_shm->
opt.timer.shared_tmo_pool_size,
1032 em_shm->
opt.timer.tmo_pool_cache, timer);
1034 if (unlikely(opool == ODP_POOL_INVALID)) {
1035 reason =
"Shared tmo handle buffer pool create failed";
1038 timer->tmo_pool = opool;
1039 em_shm->timers.shared_tmo_pool = opool;
1040 TMR_DBG_PRINT(
"Created shared tmo handle pool for total %u tmos\n",
1041 em_shm->
opt.timer.shared_tmo_pool_size);
1043 timer->tmo_pool =
em_shm->timers.shared_tmo_pool;
1047 timer->num_tmo_reserve = tmr_attr->
num_tmo;
1048 if (
em_shm->
opt.timer.shared_tmo_pool_enable) {
1049 uint32_t left =
em_shm->
opt.timer.shared_tmo_pool_size -
em_shm->timers.reserved;
1051 if (timer->num_tmo_reserve > left) {
1052 TMR_DBG_PRINT(
"Not enough tmos left in shared pool (%u)\n", left);
1053 reason =
"Not enough tmos left in shared pool";
1056 em_shm->timers.reserved += timer->num_tmo_reserve;
1057 TMR_DBG_PRINT(
"Updated shared tmo reserve by +%u to %u\n",
1058 timer->num_tmo_reserve,
em_shm->timers.reserved);
1060 timer->flags = tmr_attr->
flags;
1061 timer->plain_q_ok = capa.queue_type_plain;
1062 timer->is_ring =
false;
1064 if (odp_timer_pool_start_multi(&timer->odp_tmr_pool, 1) != 1) {
1065 reason =
"odp_timer_pool_start_multi failed";
1069 em_shm->timers.num_timers++;
1070 odp_ticketlock_unlock(&
em_shm->timers.timer_lock);
1072 TMR_DBG_PRINT(
"ret %" PRI_TMR ", total timers %u\n", TMR_I2H(i),
em_shm->timers.num_timers);
1076 cleanup_timer_create_fail(timer);
1077 odp_ticketlock_unlock(&
em_shm->timers.timer_lock);
1079 TMR_DBG_PRINT(
"ERR odp tmr pool in: clk %u, res %lu, min %lu, max %lu, num %u\n",
1080 odp_tpool_param.clk_src, odp_tpool_param.res_ns,
1081 odp_tpool_param.min_tmo, odp_tpool_param.max_tmo, odp_tpool_param.num_timers);
1083 "Timer pool create failed: %s", reason);
1087typedef enum ring_kind {
1096static bool ring_check_capa(ring_kind_t kind,
const em_timer_attr_t *ring_attr,
1098 odp_timer_clk_src_t *odp_clksrc,
1099 odp_timer_capability_t *capa)
1101#if PRE_1_50_ODP_TIMER_API
1104 if (unlikely(timer_clksrc_em2odp(em_clksrc, odp_clksrc))) {
1106 "Unsupported EM-timer clock source:%d", em_clksrc);
1110 if (unlikely(odp_timer_capability(*odp_clksrc, capa))) {
1112 "ODP timer capa failed for clk:%d", em_clksrc);
1115 if (unlikely(!capa->queue_type_sched)) {
1117 "ODP does not support scheduled q for clk:%d", em_clksrc);
1120#if !PRE_1_50_ODP_TIMER_API
1121 if (kind == RING_KIND_FREQ && unlikely(!capa->periodic.support.freq)) {
1123 "ODP_TIMER_TYPE_PERIODIC_FREQ not supported");
1127 if (unlikely(ring_attr->
priority > capa->periodic.max_priority)) {
1129 "Priority %u exceeds ODP max %u for clk:%d",
1130 ring_attr->
priority, capa->periodic.max_priority, em_clksrc);
1141static bool ring_fill_tpool_param(ring_kind_t kind,
const em_timer_attr_t *ring_attr,
1142 const odp_timer_capability_t *capa,
em_escope_t escope,
1143 odp_timer_pool_param_t *odp_tpool_param)
1145#if PRE_1_50_ODP_TIMER_API
1149 odp_tpool_param->timer_type = ODP_TIMER_TYPE_PERIODIC;
1156 "Ring flow control not supported with this ODP version");
1159 TMR_DBG_PRINT(
"Creating ODP periodic tmr pool: clk %d, res_ns %lu, base_hz %lu, priority %u\n",
1160 odp_tpool_param->clk_src, odp_tpool_param->res_ns,
1161 odp_tpool_param->periodic.base_freq_hz.integer, odp_tpool_param->priority);
1163 if (kind == RING_KIND_FREQ) {
1164 odp_tpool_param->timer_type = ODP_TIMER_TYPE_PERIODIC_FREQ;
1165 odp_tpool_param->periodic.freq.freq_hz =
1167 odp_tpool_param->periodic.freq.num = ring_attr->
freqparam.
num;
1169 odp_tpool_param->timer_type = ODP_TIMER_TYPE_PERIODIC_BASE_MUL;
1170 odp_tpool_param->periodic.base_mul.base_freq_hz.integer =
1172 odp_tpool_param->periodic.base_mul.base_freq_hz.numer =
1174 odp_tpool_param->periodic.base_mul.base_freq_hz.denom =
1176 odp_tpool_param->periodic.base_mul.max_multiplier =
1182 if (capa->periodic.max_pending_tmo == 0) {
1184 "Ring flow control not supported by ODP");
1189 "Requested max_pending_events %u exceeds ODP max %u",
1191 capa->periodic.max_pending_tmo);
1196 "Requested max_pending_events %u less than ODP min %u",
1198 capa->periodic.min_pending_tmo);
1203 odp_tpool_param->periodic.uarea_size =
sizeof(
event_hdr_t);
1204 TMR_DBG_PRINT(
"Creating ODP periodic %s tmr pool: clk %d, res_ns %lu, priority %u, max_pending_tmo %u\n",
1205 kind == RING_KIND_FREQ ?
"freq" :
"base_mul",
1206 odp_tpool_param->clk_src, odp_tpool_param->res_ns,
1207 odp_tpool_param->priority, odp_tpool_param->periodic.max_pending_tmo);
1217static bool ring_setup_tmo_handle_pool(
event_timer_t *timer, uint32_t num_tmo,
1218 const char **reason)
1220 if (!
em_shm->
opt.timer.shared_tmo_pool_enable) {
1221 odp_pool_t opool = create_tmo_handle_pool(num_tmo,
1225 if (unlikely(opool == ODP_POOL_INVALID)) {
1226 *reason =
"tmo handle pool creation failed";
1230 timer->tmo_pool = opool;
1231 TMR_DBG_PRINT(
"Created per-timer tmo handle pool %p\n", opool);
1235 if (
em_shm->timers.shared_tmo_pool == ODP_POOL_INVALID) {
1237 create_tmo_handle_pool(
em_shm->
opt.timer.shared_tmo_pool_size,
1238 em_shm->
opt.timer.tmo_pool_cache, timer);
1240 if (unlikely(opool == ODP_POOL_INVALID)) {
1241 *reason =
"Shared tmo handle pool creation failed";
1245 timer->tmo_pool = opool;
1246 em_shm->timers.shared_tmo_pool = opool;
1247 TMR_DBG_PRINT(
"Created shared tmo handle pool %p\n", opool);
1251 timer->tmo_pool =
em_shm->timers.shared_tmo_pool;
1255static em_timer_t ring_create_common(
const em_timer_attr_t *ring_attr, ring_kind_t kind)
1257 const em_escope_t escope = (kind == RING_KIND_FREQ) ?
1258 EM_ESCOPE_TIMER_RING_FREQ_CREATE :
1259 EM_ESCOPE_TIMER_RING_CREATE;
1260 const em_timer_clksrc_t em_clksrc = (kind == RING_KIND_FREQ) ?
1262 ring_attr->ringparam.clk_src;
1263 const uint64_t res_ns = (kind == RING_KIND_FREQ) ?
1265 ring_attr->ringparam.res_ns;
1267 odp_timer_pool_param_t odp_tpool_param;
1268 odp_timer_clk_src_t odp_clksrc;
1269 odp_timer_capability_t capa;
1271 odp_timer_pool_param_init(&odp_tpool_param);
1272 odp_tpool_param.exp_mode = ODP_TIMER_EXP_AFTER;
1273 odp_tpool_param.num_timers = ring_attr->
num_tmo;
1276 if (!ring_check_capa(kind, ring_attr, em_clksrc, escope, &odp_clksrc, &capa))
1279 odp_tpool_param.clk_src = odp_clksrc;
1280 odp_tpool_param.res_hz = 0;
1281 odp_tpool_param.res_ns = res_ns;
1282 odp_tpool_param.priority = ring_attr->
priority;
1285 if (!ring_fill_tpool_param(kind, ring_attr, &capa, escope, &odp_tpool_param))
1291 odp_ticketlock_lock(&tmrs->timer_lock);
1293#if PRE_1_50_ODP_TIMER_API
1296 uint32_t left =
em_shm->
opt.timer.ring.timer_event_pool_size - tmrs->ring_reserved;
1298 if (ring_attr->
num_tmo > left) {
1299 odp_ticketlock_unlock(&tmrs->timer_lock);
1301 "Too few ring timeout events left (req %u/%u)",
1309 int i = find_free_timer_index();
1311 if (unlikely(i >= EM_ODP_MAX_TIMERS)) {
1312 odp_ticketlock_unlock(&tmrs->timer_lock);
1320 char timer_pool_name[ODP_TIMER_POOL_NAME_LEN];
1321 const char *name = ring_attr->
name;
1322 const char *reason =
"";
1324 if (ring_attr->
name[0] ==
'\0') {
1325 snprintf(timer_pool_name, ODP_TIMER_POOL_NAME_LEN,
1326 "EM-timer-%d", timer->idx);
1327 name = timer_pool_name;
1330 timer->odp_tmr_pool = odp_timer_pool_create(name, &odp_tpool_param);
1331 if (unlikely(timer->odp_tmr_pool == ODP_TIMER_POOL_INVALID)) {
1332 reason =
"odp_timer_pool_create failed";
1335 TMR_DBG_PRINT(
"Created %s timer: %s with idx: %d\n",
1336 kind == RING_KIND_FREQ ?
"ring freq" :
"ring", name, timer->idx);
1339 if (!ring_setup_tmo_handle_pool(timer, ring_attr->
num_tmo, &reason))
1342 timer->num_tmo_reserve = ring_attr->
num_tmo;
1343 if (
em_shm->
opt.timer.shared_tmo_pool_enable) {
1344 uint32_t left =
em_shm->
opt.timer.shared_tmo_pool_size -
em_shm->timers.reserved;
1346 if (timer->num_tmo_reserve > left) {
1347 TMR_DBG_PRINT(
"Not enough tmos left in shared pool (%u)\n", left);
1348 reason =
"Not enough tmos left in shared pool";
1351 em_shm->timers.reserved += timer->num_tmo_reserve;
1352 TMR_DBG_PRINT(
"Updated shared tmo reserve by +%u to %u\n",
1353 timer->num_tmo_reserve,
em_shm->timers.reserved);
1356#if PRE_1_50_ODP_TIMER_API
1360 if (tmrs->ring_tmo_pool == ODP_POOL_INVALID) {
1361 odp_pool_param_t odp_tmo_pool_param;
1362 char pool_name[ODP_POOL_NAME_LEN];
1364 odp_pool_param_init(&odp_tmo_pool_param);
1365 odp_tmo_pool_param.type = ODP_POOL_TIMEOUT;
1366 odp_tmo_pool_param.tmo.cache_size =
em_shm->
opt.timer.ring.timer_event_pool_cache;
1367 odp_tmo_pool_param.tmo.num =
em_shm->
opt.timer.ring.timer_event_pool_size;
1368 odp_tmo_pool_param.tmo.uarea_size =
sizeof(
event_hdr_t);
1369 odp_tmo_pool_param.stats.all = 0;
1370 snprintf(pool_name, ODP_POOL_NAME_LEN,
"Ring-%d-tmo-pool", timer->idx);
1371 tmrs->ring_tmo_pool = odp_pool_create(pool_name, &odp_tmo_pool_param);
1372 if (unlikely(tmrs->ring_tmo_pool == ODP_POOL_INVALID)) {
1373 reason =
"odp timeout event pool creation failed";
1376 TMR_DBG_PRINT(
"Created ODP-timeout event pool %p: '%s'\n",
1377 tmrs->ring_tmo_pool, pool_name);
1380 tmrs->ring_reserved += ring_attr->
num_tmo;
1381 TMR_DBG_PRINT(
"Updated ring reserve by +%u to %u\n", ring_attr->
num_tmo,
1382 tmrs->ring_reserved);
1387 timer->num_ring_reserve = ring_attr->
num_tmo;
1388 timer->flags = ring_attr->
flags;
1389 timer->plain_q_ok = capa.queue_type_plain;
1390 timer->is_ring =
true;
1391 tmrs->num_ring_create_calls++;
1393 if (odp_timer_pool_start_multi(&timer->odp_tmr_pool, 1) != 1) {
1394 reason =
"odp_timer_pool_start_multi failed";
1398 odp_ticketlock_unlock(&
em_shm->timers.timer_lock);
1400 TMR_DBG_PRINT(
"ret %" PRI_TMR ", total timers %u\n", TMR_I2H(i), tmrs->num_timers);
1404 cleanup_timer_create_fail(timer);
1405 odp_ticketlock_unlock(&tmrs->timer_lock);
1407 "Ring%s timer create failed: %s",
1408 kind == RING_KIND_FREQ ?
" freq" :
"", reason);
1417 "Timer is disabled!");
1421 if (
EM_CHECK_LEVEL > 0 && unlikely(check_timer_attr_ring(ring_attr) ==
false)) {
1423 "NULL or incorrect attribute");
1427 return ring_create_common(ring_attr, RING_KIND_BASE_MUL);
1432#if PRE_1_50_ODP_TIMER_API
1435 "Freq-based ring timer not supported by this ODP version");
1441 "Timer is disabled!");
1445 if (
EM_CHECK_LEVEL > 0 && unlikely(check_timer_attr_ring_freq(ring_attr) ==
false))
1448 return ring_create_common(ring_attr, RING_KIND_FREQ);
1455 int i = TMR_H2I(tmr);
1457 odp_pool_t pool_fail = ODP_POOL_INVALID;
1460 odp_ticketlock_lock(&tmrs->timer_lock);
1461 if (unlikely(!is_timer_valid(tmr))) {
1462 odp_ticketlock_unlock(&tmrs->timer_lock);
1464 "Invalid timer:%" PRI_TMR "", tmr);
1467 if (tmrs->timer[i].tmo_pool != tmrs->shared_tmo_pool) {
1468 if (unlikely(odp_pool_destroy(tmrs->timer[i].tmo_pool) != 0)) {
1470 pool_fail = tmrs->timer[i].tmo_pool;
1472 TMR_DBG_PRINT(
"Deleted odp pool %p\n", tmrs->timer[i].tmo_pool);
1475 tmrs->timer[i].tmo_pool = ODP_POOL_INVALID;
1476 odp_timer_pool_destroy(tmrs->timer[i].odp_tmr_pool);
1477 tmrs->timer[i].odp_tmr_pool = ODP_TIMER_POOL_INVALID;
1480 if (tmrs->timer[i].is_ring && tmrs->num_rings) {
1482 if (tmrs->num_rings < 1)
1483 TMR_DBG_PRINT(
"Last ring deleted\n");
1484#if PRE_1_50_ODP_TIMER_API
1485 tmrs->ring_reserved -= tmrs->timer[i].num_ring_reserve;
1486 TMR_DBG_PRINT(
"Updated ring reserve by -%u to %u\n",
1487 tmrs->timer[i].num_ring_reserve, tmrs->ring_reserved);
1489 tmrs->timer[i].num_ring_reserve = 0;
1493 if (tmrs->shared_tmo_pool != ODP_POOL_INVALID) {
1494 tmrs->reserved -= tmrs->timer[i].num_tmo_reserve;
1495 TMR_DBG_PRINT(
"Updated tmo reserve by -%u to %u\n",
1496 tmrs->timer[i].num_tmo_reserve, tmrs->reserved);
1497 tmrs->timer[i].num_tmo_reserve = 0;
1499 if (tmrs->num_timers == 0 && tmrs->shared_tmo_pool != ODP_POOL_INVALID) {
1501 if (unlikely(odp_pool_destroy(tmrs->shared_tmo_pool) != 0)) {
1503 pool_fail = tmrs->shared_tmo_pool;
1505 TMR_DBG_PRINT(
"Deleted shared tmo pool %p\n", tmrs->shared_tmo_pool);
1506 tmrs->shared_tmo_pool = ODP_POOL_INVALID;
1510 odp_ticketlock_unlock(&tmrs->timer_lock);
1511 if (unlikely(rv !=
EM_OK)) {
1513 "timer %p delete fail, odp pool %p fail\n", tmr, pool_fail);
1515 TMR_DBG_PRINT(
"ok, deleted timer %p, num_timers %u\n", tmr, tmrs->num_timers);
1522 int i = TMR_H2I(tmr);
1527 return odp_timer_current_tick(tmrs->timer[i].odp_tmr_pool);
1538 const queue_elem_t *
const q_elem = queue_elem_get(queue);
1541 if (unlikely(!is_timer_valid(tmr))) {
1543 "Invalid timer:%" PRI_TMR "", tmr);
1546 if (unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
1552 if (unlikely(!is_queue_valid_type(tmr, q_elem))) {
1558 if (unlikely(!check_tmo_flags(flags))) {
1560 "Tmr:%" PRI_TMR ": inv. tmo-flags:0x%x",
1566 int i = TMR_H2I(tmr);
1569 em_shm->timers.timer[i].is_ring &&
1572 "Tmr:%" PRI_TMR ": asking oneshot with ring timer!",
1577 odp_buffer_t tmo_buf = odp_buffer_alloc(
em_shm->timers.timer[i].tmo_pool);
1579 if (unlikely(tmo_buf == ODP_BUFFER_INVALID)) {
1581 "Tmr:%" PRI_TMR ": tmo pool exhausted", tmr);
1586 odp_timer_pool_t odptmr =
em_shm->timers.timer[i].odp_tmr_pool;
1588 const void *userptr = NULL;
1593#if PRE_1_50_ODP_TIMER_API
1594 tmo->odp_timer = odp_timer_alloc(odptmr, q_elem->
odp_queue, userptr);
1595 if (unlikely(tmo->odp_timer == ODP_TIMER_INVALID)) {
1597 "Tmr:%" PRI_TMR ": odp_timer_alloc() failed", tmr);
1598 odp_buffer_free(tmo_buf);
1607 if (!
em_shm->timers.timer[i].is_ring) {
1608 tmo->odp_timer = odp_timer_alloc(odptmr, q_elem->
odp_queue, userptr);
1609 if (unlikely(tmo->odp_timer == ODP_TIMER_INVALID)) {
1611 "Tmr:%" PRI_TMR ": odp_timer_alloc() failed", tmr);
1612 odp_buffer_free(tmo_buf);
1616 tmo->odp_timer = ODP_TIMER_INVALID;
1622 tmo->odp_timer_pool = odptmr;
1624 tmo->odp_buffer = tmo_buf;
1627 tmo->is_ring =
em_shm->timers.timer[i].is_ring;
1628 tmo->odp_timeout = ODP_EVENT_INVALID;
1630#if PRE_1_50_ODP_TIMER_API
1631 tmo->ring_tmo_pool =
em_shm->timers.ring_tmo_pool;
1634 odp_event_t odp_tmo_event = alloc_odp_timeout(tmo);
1636 if (unlikely(odp_tmo_event == ODP_EVENT_INVALID)) {
1638 "Ring: odp timeout event allocation failed");
1639 odp_timer_free(tmo->odp_timer);
1640 odp_buffer_free(tmo_buf);
1643 tmo->odp_timeout = odp_tmo_event;
1644 TMR_DBG_PRINT(
"Ring: allocated odp timeout ev %p\n", tmo->odp_timeout);
1647 tmo->ring_tmo_pool = ODP_POOL_INVALID;
1648 tmo->user_ptr = userptr;
1649 tmo->multiplier = 0;
1653 if (EM_TIMER_TMO_STATS)
1657 TMR_DBG_PRINT(
"ODP timer %p allocated\n", tmo->odp_timer);
1658 TMR_DBG_PRINT(
"tmo %p created\n", tmo);
1667 "Invalid args: tmo:%" PRI_TMO, tmo);
1676 "Invalid tmo buffer");
1680 "Invalid tmo state:%d", tmo_state);
1682#if PRE_1_50_ODP_TIMER_API
1685 "Invalid tmo odp_timer, deleted?");
1690 "Invalid tmo odp_timer, deleted?");
1694 TMR_DBG_PRINT(
"ODP timer %p\n", tmo->odp_timer);
1696 odp_atomic_store_rel_u32(&tmo->state, EM_TMO_STATE_UNKNOWN);
1698#if PRE_1_50_ODP_TIMER_API
1699 int fret = odp_timer_free(tmo->odp_timer);
1702 "odp timer free failed!?, rv %d\n", fret);
1707 if (tmo->is_ring && tmo->odp_timeout != ODP_EVENT_INVALID) {
1708 TMR_DBG_PRINT(
"ring: free unused ODP timeout ev %p\n", tmo->odp_timeout);
1709 free_odp_timeout(tmo->odp_timeout);
1710 tmo->odp_timeout = ODP_EVENT_INVALID;
1714 if (tmo->odp_timer != ODP_TIMER_INVALID) {
1715 int fret = odp_timer_free(tmo->odp_timer);
1718 "odp timer free failed!?, rv %d\n", fret);
1721 odp_buffer_t tmp = tmo->odp_buffer;
1723 tmo->odp_timer = ODP_TIMER_INVALID;
1724 tmo->odp_buffer = ODP_BUFFER_INVALID;
1726 odp_buffer_free(tmp);
1728 TMR_DBG_PRINT(
"tmo %p delete ok\n", tmo);
1744 "Invalid tmo buffer");
1748 "Cannot set periodic tmo, use _set_periodic()");
1754 "Invalid tmo state:%d", tmo_state);
1757 tmo->odp_timer == ODP_TIMER_INVALID,
1759 "Invalid tmo odp_timer");
1762 odp_event_t odp_ev = event_em2odp(tmo_ev);
1763 bool esv_ena = esv_enabled();
1764 odp_timer_start_t startp;
1770 !is_event_type_valid(evtype_major),
1772 "Invalid event type:%u", evtype_major);
1775 "Invalid event type: timer-ring");
1779 evstate_usr2em(tmo_ev, ev_hdr, EVSTATE__TMO_SET_ABS);
1782 startp.tick_type = ODP_TIMER_TICK_ABS;
1783 startp.tick = ticks_abs;
1784 startp.tmo_ev = odp_ev;
1788 int odpret = odp_timer_start(tmo->odp_timer, &startp);
1790 if (unlikely(odpret != ODP_TIMER_SUCCESS)) {
1795 evstate_usr2em_revert(tmo_ev, ev_hdr, EVSTATE__TMO_SET_ABS__FAIL);
1800 TMR_DBG_PRINT(
"TOONEAR, skip ErrH\n");
1804 TMR_DBG_PRINT(
"BUSY, skip ErrH\n");
1808 "odp_timer_start():%d", odpret);
1810 TMR_DBG_PRINT(
"OK\n");
1825 "%s: Periodic no longer supported", __func__);
1831 "Invalid tmo buffer");
1837 "Invalid tmo state:%d", tmo_state);
1841 odp_event_t odp_ev = event_em2odp(tmo_ev);
1842 bool esv_ena = esv_enabled();
1843 odp_timer_start_t startp;
1849 !is_event_type_valid(evtype_major),
1851 "Invalid event type:%u", evtype_major);
1854 "Invalid event type: timer-ring");
1858 evstate_usr2em(tmo_ev, ev_hdr, EVSTATE__TMO_SET_REL);
1861 startp.tick_type = ODP_TIMER_TICK_REL;
1862 startp.tick = ticks_rel;
1863 startp.tmo_ev = odp_ev;
1867 int odpret = odp_timer_start(tmo->odp_timer, &startp);
1869 if (unlikely(odpret != ODP_TIMER_SUCCESS)) {
1874 evstate_usr2em_revert(tmo_ev, ev_hdr, EVSTATE__TMO_SET_REL__FAIL);
1879 TMR_DBG_PRINT(
"TOONEAR, skip ErrH\n");
1883 TMR_DBG_PRINT(
"BUSY, skip ErrH\n");
1887 "odp_timer_start():%d", odpret);
1889 TMR_DBG_PRINT(
"OK\n");
1906 "Invalid tmo buffer");
1909 "Not periodic tmo");
1915 "Invalid tmo state:%d", tmo_state);
1919 odp_event_t odp_ev = event_em2odp(tmo_ev);
1920 bool esv_ena = esv_enabled();
1921 odp_timer_start_t startp;
1927 !is_event_type_valid(evtype_major),
1929 "invalid event type");
1932 "Invalid event type: timer-ring");
1936 evstate_usr2em(tmo_ev, ev_hdr, EVSTATE__TMO_SET_PERIODIC);
1938 TMR_DBG_PRINT(
"start %lu, period %lu\n", start_abs, period);
1940 tmo->period = period;
1942 start_abs = odp_timer_current_tick(tmo->odp_timer_pool) + period;
1943 tmo->last_tick = start_abs;
1944 TMR_DBG_PRINT(
"last_tick %lu, now %lu\n", tmo->last_tick,
1945 odp_timer_current_tick(tmo->odp_timer_pool));
1948 startp.tick_type = ODP_TIMER_TICK_ABS;
1949 startp.tick = start_abs;
1950 startp.tmo_ev = odp_ev;
1954 int odpret = odp_timer_start(tmo->odp_timer, &startp);
1956 if (unlikely(odpret != ODP_TIMER_SUCCESS)) {
1961 evstate_usr2em_revert(tmo_ev, ev_hdr, EVSTATE__TMO_SET_PERIODIC__FAIL);
1963 TMR_DBG_PRINT(
"diff to tmo %ld\n",
1964 (int64_t)tmo->last_tick -
1965 (int64_t)odp_timer_current_tick(tmo->odp_timer_pool));
1970 TMR_DBG_PRINT(
"TOONEAR, skip ErrH\n");
1974 TMR_DBG_PRINT(
"BUSY, skip ErrH\n");
1978 EM_ESCOPE_TMO_SET_PERIODIC,
1979 "odp_timer_start():%d", odpret);
1981 TMR_DBG_PRINT(
"OK\n");
1987 uint64_t multiplier)
1991 "Inv.args: tmo UNDEF");
1995 "Invalid tmo buffer");
1998 "Not periodic tmo");
2002 "Timer created with EM_TIMER_FLAG_RING_FREQ, use em_tmo_set_periodic_ring_freq()");
2009 "Invalid tmo state:%d", tmo_state);
2012#if PRE_1_50_ODP_TIMER_API
2013 odp_timer_periodic_start_t startp;
2014 odp_event_t odp_ev = tmo->odp_timeout;
2016 tmo->odp_timeout = ODP_EVENT_INVALID;
2018 if (odp_ev == ODP_EVENT_INVALID) {
2019 odp_event_t odp_tmo_event = alloc_odp_timeout(tmo);
2021 if (unlikely(odp_tmo_event == ODP_EVENT_INVALID))
2023 "Ring: odp timeout event allocation failed");
2024 odp_ev = odp_tmo_event;
2027 TMR_DBG_PRINT(
"ring tmo start_abs %lu, M=%lu, odp ev=%p\n", start_abs, multiplier, odp_ev);
2028 startp.first_tick = start_abs;
2029 startp.freq_multiplier = multiplier;
2030 startp.tmo_ev = odp_ev;
2037 if (tmo->odp_timer != ODP_TIMER_INVALID && tmo->multiplier != multiplier) {
2043 "Cannot change multiplier while tmo is active");
2044 odp_timer_free(tmo->odp_timer);
2045 tmo->odp_timer = ODP_TIMER_INVALID;
2048 if (tmo->odp_timer == ODP_TIMER_INVALID) {
2049 const queue_elem_t *q_elem = queue_elem_get(tmo->queue);
2054 "Invalid queue:%" PRI_QUEUE "", tmo->queue);
2057 odp_timer_periodic_param_t pparams;
2059 odp_timer_periodic_param_init(&pparams);
2061 pparams.user_ptr = tmo->user_ptr;
2062 pparams.base_mul.multiplier = multiplier;
2063 pparams.uarea_init.init_fn = ring_tmo_uarea_init;
2064 pparams.uarea_init.args = tmo;
2066 tmo->odp_timer = odp_timer_periodic_alloc(tmo->odp_timer_pool, &pparams);
2067 if (unlikely(tmo->odp_timer == ODP_TIMER_INVALID))
2069 "odp_timer_periodic_alloc() failed");
2070 tmo->multiplier = multiplier;
2071 TMR_DBG_PRINT(
"Allocated periodic ODP timer %p, M=%lu\n",
2072 tmo->odp_timer, multiplier);
2075 TMR_DBG_PRINT(
"ring tmo start_abs %lu, M=%lu\n", start_abs, multiplier);
2077 odp_timer_periodic_start_t startp;
2079 startp.first_tick = start_abs;
2082 int odpret = odp_timer_periodic_start(tmo->odp_timer, &startp);
2084 if (unlikely(odpret != ODP_TIMER_SUCCESS)) {
2090 TMR_DBG_PRINT(
"TOONEAR, skip ErrH\n");
2094 TMR_DBG_PRINT(
"BUSY, skip ErrH\n");
2098 EM_ESCOPE_TMO_SET_PERIODIC_RING,
2099 "odp_timer_periodic_start(): ret %d", odpret);
2102 TMR_DBG_PRINT(
"OK\n");
2110#if PRE_1_50_ODP_TIMER_API
2118 "Inv.args: tmo UNDEF");
2122 "Invalid tmo buffer");
2125 "Not periodic tmo");
2127 !(
em_shm->timers.timer[TMR_H2I(tmo->timer)].flags &
2130 "Timer not created with EM_TIMER_FLAG_RING_FREQ");
2133 "Invalid freq_hz, denom cannot be 0 if numer is not 0");
2143 "Invalid tmo state:%d", tmo_state);
2151 if (tmo->odp_timer != ODP_TIMER_INVALID &&
2160 "Cannot change freq while tmo is active");
2161 odp_timer_free(tmo->odp_timer);
2162 tmo->odp_timer = ODP_TIMER_INVALID;
2165 if (tmo->odp_timer == ODP_TIMER_INVALID) {
2166 const queue_elem_t *q_elem = queue_elem_get(tmo->queue);
2171 "Invalid queue:%" PRI_QUEUE "", tmo->queue);
2174 odp_timer_periodic_param_t pparams;
2176 odp_timer_periodic_param_init(&pparams);
2178 pparams.user_ptr = tmo->user_ptr;
2179 pparams.freq.freq_hz.integer = freq_hz.
integer;
2180 pparams.freq.freq_hz.numer = freq_hz.
numer;
2181 pparams.freq.freq_hz.denom = freq_hz.
denom;
2182 pparams.uarea_init.init_fn = ring_tmo_uarea_init;
2183 pparams.uarea_init.args = tmo;
2185 tmo->odp_timer = odp_timer_periodic_alloc(tmo->odp_timer_pool, &pparams);
2186 if (unlikely(tmo->odp_timer == ODP_TIMER_INVALID))
2188 EM_ESCOPE_TMO_SET_PERIODIC_RING_FREQ,
2189 "odp_timer_periodic_alloc() failed");
2193 TMR_DBG_PRINT(
"Allocated periodic freq ODP timer %p, freq=%lu %lu/%lu.\n",
2197 TMR_DBG_PRINT(
"ring freq tmo start_abs %lu, freq=%lu %lu/%lu\n",
2200 odp_timer_periodic_start_t startp;
2202 startp.first_tick = start_abs;
2205 int odpret = odp_timer_periodic_start(tmo->odp_timer, &startp);
2207 if (unlikely(odpret != ODP_TIMER_SUCCESS)) {
2213 TMR_DBG_PRINT(
"TOONEAR, skip ErrH\n");
2217 TMR_DBG_PRINT(
"BUSY, skip ErrH\n");
2221 EM_ESCOPE_TMO_SET_PERIODIC_RING_FREQ,
2222 "odp_timer_periodic_start(): ret %d", odpret);
2225 TMR_DBG_PRINT(
"OK\n");
2235 "Invalid args: tmo:%" PRI_TMO " cur_event:%p",
2242 "Invalid tmo buffer");
2245 "Invalid tmo odp_timer");
2255 TMR_DBG_PRINT(
"ODP tmo %p\n", tmo->odp_timer);
2262 "odp periodic cancel fail");
2267 odp_event_t odp_ev = ODP_EVENT_INVALID;
2268 int ret = odp_timer_cancel(tmo->odp_timer, &odp_ev);
2270 if (ret == ODP_TIMER_TOO_NEAR) {
2274 "ODP timer cancel return TOONEAR but return event!");
2276 TMR_DBG_PRINT(
"ODP returned TOONEAR\n");
2282 "ODP timer cancel fail!");
2291 "Invalid tmo event from odp_timer_cancel");
2294 em_event_t tmo_ev = event_odp2em(odp_ev);
2302 tmo_ev = evstate_em2usr(tmo_ev, ev_hdr, EVSTATE__TMO_CANCEL);
2304 *cur_event = tmo_ev;
2305 TMR_DBG_PRINT(
"OK\n");
2320 int tries = EM_TIMER_ACK_TRIES;
2322 odp_timer_start_t startp;
2324 startp.tick_type = ODP_TIMER_TICK_ABS;
2325 startp.tmo_ev = odp_ev;
2332 startp.tick = tmo->last_tick;
2333 ret = odp_timer_start(tmo->odp_timer, &startp);
2335 if (likely(ret == ODP_TIMER_SUCCESS))
2338#if !PRE_1_50_ODP_TIMER_API
2344 if (unlikely(ret == ODP_TIMER_BUSY)) {
2345 if (unlikely(--tries < 1)) {
2348 "Tmo ACK: too many retries (busy):%u",
2349 EM_TIMER_ACK_TRIES);
2352 TMR_DBG_PRINT(
"BUSY, retry\n");
2362 if (ret != ODP_TIMER_TOO_NEAR) {
2363 TMR_DBG_PRINT(
"ODP return %d\n"
2364 "tmo tgt/tick now %lu/%lu\n",
2365 ret, tmo->last_tick,
2366 odp_timer_current_tick(tmo->odp_timer_pool));
2368 "Tmo ACK: failed to renew tmo (odp ret %d)",
2374 if (EM_TIMER_TMO_STATS)
2376 TMR_DBG_PRINT(
"late, tgt/now %lu/%lu\n", tmo->last_tick,
2377 odp_timer_current_tick(tmo->odp_timer_pool));
2380 return handle_ack_noskip(next_tmo_ev, ev_hdr, tmo->queue);
2383 handle_ack_skip(tmo);
2385 if (unlikely(--tries < 1)) {
2388 "Tmo ACK: too many retries:%u",
2389 EM_TIMER_ACK_TRIES);
2392 }
while (ret != ODP_TIMER_SUCCESS);
2401 evstate_usr2em_revert(next_tmo_ev, ev_hdr, EVSTATE__TMO_ACK__FAIL);
2415 "Tmo ACK: invalid tmo buffer");
2418 "Tmo ACK: Not a periodic tmo");
2420 if (EM_TIMER_TMO_STATS)
2428 "Tmo ACK: Given tmo event is not an EM event");
2432 "Tmo ACK: Given tmo event is a timer-ring event");
2434 odp_event_t odp_ev = event_em2odp(next_tmo_ev);
2445 "Tmo ACK: invalid tmo state:%d", tmo_state);
2448 bool esv_ena = esv_enabled();
2451 evstate_usr2em(next_tmo_ev, ev_hdr, EVSTATE__TMO_ACK);
2457 tmo->last_tick += tmo->period;
2459 return tmo_ack_rearm(tmo, next_tmo_ev, ev_hdr, odp_ev, esv_ena);
2472 "Tmo ring ACK: invalid tmo buffer");
2475 "Tmo ring ACK: Not a ring tmo");
2477 if (EM_TIMER_TMO_STATS)
2485 "Tmo ring ACK: Given tmo event is not an EM event");
2492 odp_event_t odp_ev = event_em2odp(tmo_ev);
2494 return ack_ring_timeout_event(tmo, tmo_ev, tmo_state, ev_hdr, odp_ev);
2499 odp_ticketlock_lock(&
em_shm->timers.timer_lock);
2501 const uint32_t num_timers =
em_shm->timers.num_timers;
2503 if (tmr_list && max > 0 && num_timers > 0) {
2506 for (
int i = 0; i < EM_ODP_MAX_TIMERS; i++) {
2507 if (
em_shm->timers.timer[i].odp_tmr_pool != ODP_TIMER_POOL_INVALID) {
2508 tmr_list[num] = TMR_I2H(i);
2516 odp_ticketlock_unlock(&
em_shm->timers.timer_lock);
2523 odp_timer_pool_info_t poolinfo;
2524 int i = TMR_H2I(tmr);
2531 "Inv.args: timer:%" PRI_TMR " tmr_attr:%p",
2535 ret = odp_timer_pool_info(
em_shm->timers.timer[i].odp_tmr_pool, &poolinfo);
2537 "ODP timer pool info failed");
2539 timer_clksrc_odp2em(poolinfo.param.clk_src, &clk);
2541 if (poolinfo.param.timer_type == ODP_TIMER_TYPE_SINGLE) {
2550#if PRE_1_50_ODP_TIMER_API
2562 }
else if (poolinfo.param.timer_type == ODP_TIMER_TYPE_PERIODIC_BASE_MUL) {
2564 poolinfo.param.periodic.base_mul.base_freq_hz.integer;
2566 poolinfo.param.periodic.base_mul.base_freq_hz.numer;
2568 poolinfo.param.periodic.base_mul.base_freq_hz.denom;
2570 poolinfo.param.periodic.base_mul.max_multiplier;
2578 (
em_fract_u64_t *)(uintptr_t)poolinfo.param.periodic.freq.freq_hz;
2579 tmr_attr->
freqparam.
num = poolinfo.param.periodic.freq.num;
2588 tmr_attr->
num_tmo = poolinfo.param.num_timers;
2590 tmr_attr->
priority = poolinfo.param.priority;
2592 strncpy(tmr_attr->
name, poolinfo.name, EM_TIMER_NAME_LEN - 1);
2593 tmr_attr->
name[EM_TIMER_NAME_LEN - 1] =
'\0';
2603 "Invalid timer:%" PRI_TMR "", tmr);
2607 return odp_timer_ns_to_tick(tmrs->timer[TMR_H2I(tmr)].odp_tmr_pool,
2608 1000ULL * 1000ULL * 1000ULL);
2617 "Invalid timer:%" PRI_TMR "", tmr);
2621 return odp_timer_tick_to_ns(tmrs->timer[TMR_H2I(tmr)].odp_tmr_pool, ticks);
2630 "Invalid timer:%" PRI_TMR "", tmr);
2634 return odp_timer_ns_to_tick(tmrs->timer[TMR_H2I(tmr)].odp_tmr_pool, ns);
2641 return EM_TMO_STATE_UNKNOWN;
2643 if (
EM_CHECK_LEVEL > 1 && !odp_buffer_is_valid(tmo->odp_buffer)) {
2645 return EM_TMO_STATE_UNKNOWN;
2648 return odp_atomic_load_acq_u32(&tmo->state);
2659 "Invalid tmo buffer");
2664 if (EM_TIMER_TMO_STATS) {
2685 if (
EM_CHECK_LEVEL > 1 && unlikely(!can_have_tmo_type(evtype_major))) {
2687 "Invalid event type:%u", evtype_major);
2693 "Invalid tmo event type, header corrupted?");
2715 odp_event_t odp_event = event_em2odp(event);
2716 odp_event_type_t evtype = odp_event_type(odp_event);
2718 if (unlikely(evtype != ODP_EVENT_TIMEOUT))
2726 return odp_timeout_user_ptr(odp_timeout_from_event(odp_event));
2735 if (
EM_CHECK_LEVEL > 1 && !odp_buffer_is_valid(tmo->odp_buffer)) {
2745 return (uint64_t)timer;
2750 return (uint64_t)tmo;
#define INTERNAL_ERROR(error, escope, fmt,...)
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
struct event_hdr event_hdr_t
#define EM_CHECK_INIT_CALLED
@ EM_TIMER_FLAG_RING_FREQ
#define EM_TIMER_CLKSRC_DEFAULT
struct em_timer_timeout_t * em_tmo_t
#define EM_EVENT_GROUP_UNDEF
@ EM_ERR_OPERATION_FAILED
em_status_t em_send(em_event_t event, em_queue_t queue)
void em_free(em_event_t event)
@ EM_EVENT_TYPE_TIMER_IND
@ EM_QUEUE_TYPE_UNSCHEDULED
em_status_t em_timer_capability(em_timer_capability_t *capa, em_timer_clksrc_t clk_src)
em_status_t em_tmo_set_abs(em_tmo_t tmo, em_timer_tick_t ticks_abs, em_event_t tmo_ev)
em_status_t em_timer_ring_freq_capability(em_timer_ring_freq_param_t *ring)
Check frequency-based periodic ring timer capability.
int em_timer_list(em_timer_t tmr_list[], int max)
uint64_t em_timer_freq(em_timer_t tmr)
uint64_t em_tmo_to_u64(em_tmo_t tmo)
em_status_t em_tmo_stats(em_tmo_t tmo, em_tmo_stats_t *stat)
em_status_t em_timer_delete(em_timer_t tmr)
em_status_t em_timer_ring_attr_init(em_timer_attr_t *ring_attr, em_timer_clksrc_t clk_src, uint64_t base_hz, uint64_t max_mul, uint64_t res_ns)
em_status_t em_timer_ring_freq_attr_init(em_timer_attr_t *ring_attr, em_timer_clksrc_t clk_src, em_fract_u64_t *freq_hz, uint32_t num, uint64_t res_ns)
em_timer_tick_t em_timer_ns_to_tick(em_timer_t tmr, uint64_t ns)
em_tmo_state_t em_tmo_state(em_tmo_t tmo)
void * em_tmo_userptr(em_event_t event, em_tmo_t *tmo)
em_tmo_t em_tmo_create(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue)
em_timer_t em_timer_create(const em_timer_attr_t *tmr_attr)
em_status_t em_tmo_set_periodic_ring(em_tmo_t tmo, em_timer_tick_t start_abs, uint64_t multiplier)
em_status_t em_tmo_delete(em_tmo_t tmo)
em_status_t em_tmo_cancel(em_tmo_t tmo, em_event_t *cur_event)
em_tmo_type_t em_tmo_type(em_event_t event, em_tmo_t *tmo, bool reset)
em_timer_t em_timer_ring_create(const em_timer_attr_t *ring_attr)
em_status_t em_tmo_set_periodic(em_tmo_t tmo, em_timer_tick_t start_abs, em_timer_tick_t period, em_event_t tmo_ev)
em_timer_tick_t em_timer_current_tick(em_timer_t tmr)
em_status_t em_tmo_ring_ack(em_tmo_t tmo, em_event_t tmo_ev)
em_timer_t em_timer_ring_freq_create(const em_timer_attr_t *ring_attr)
em_status_t em_tmo_set_rel(em_tmo_t tmo, em_timer_tick_t ticks_rel, em_event_t tmo_ev)
em_status_t em_tmo_set_periodic_ring_freq(em_tmo_t tmo, em_timer_tick_t start_abs, em_fract_u64_t freq_hz)
uint64_t em_timer_tick_to_ns(em_timer_t tmr, em_timer_tick_t ticks)
uint64_t em_timer_to_u64(em_timer_t timer)
em_tmo_t em_tmo_create_arg(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue, em_tmo_args_t *args)
em_status_t em_timer_attr(em_timer_t tmr, em_timer_attr_t *tmr_attr)
void em_timer_attr_init(em_timer_attr_t *tmr_attr)
em_timer_t em_tmo_timer(em_tmo_t tmo)
em_status_t em_timer_ring_capability(em_timer_ring_param_t *ring)
Check periodic ring timer capability.
em_status_t em_tmo_ack(em_tmo_t tmo, em_event_t next_tmo_ev)
em_status_t em_timer_res_capability(em_timer_res_param_t *res, em_timer_clksrc_t clk_src)
em_timer_ring_freq_param_t freqparam
em_timer_ring_param_t ringparam
char name[EM_TIMER_NAME_LEN]
uint32_t __internal_check
uint32_t max_pending_events
em_timer_res_param_t resparam
uint32_t max_pending_events
em_fract_u64_t max_base_hz
em_timer_res_param_t max_tmo
uint32_t min_pending_events
struct em_timer_capability_t::@27::@28 support
em_fract_u64_t max_freq_hz
struct em_timer_capability_t::@27 ring
em_timer_res_param_t max_res
em_fract_u64_t min_base_hz
em_fract_u64_t min_freq_hz
em_timer_clksrc_t clk_src
em_timer_clksrc_t clk_src
em_timer_clksrc_t clk_src
uint64_t num_period_skips
ev_hdr_user_area_t user_area
union event_hdr::@43 flags
em_event_type_t event_type