1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Cavium, Inc
5 #include "timvf_evdev.h"
9 RTE_INIT(otx_timvf_init_log
)
11 otx_logtype_timvf
= rte_log_register("pmd.event.octeontx.timer");
12 if (otx_logtype_timvf
>= 0)
13 rte_log_set_level(otx_logtype_timvf
, RTE_LOG_NOTICE
);
16 struct __rte_packed timvf_mbox_dev_info
{
17 uint64_t ring_active
[4];
21 /* Response messages */
25 MBOX_RET_INTERNAL_ERR
,
29 timvf_mbox_dev_info_get(struct timvf_mbox_dev_info
*info
)
31 struct octeontx_mbox_hdr hdr
= {0};
32 uint16_t len
= sizeof(struct timvf_mbox_dev_info
);
34 hdr
.coproc
= TIM_COPROC
;
35 hdr
.msg
= TIM_GET_DEV_INFO
;
36 hdr
.vfid
= 0; /* TIM DEV is always 0. TIM RING ID changes. */
39 return octeontx_mbox_send(&hdr
, NULL
, 0, info
, len
);
43 timvf_ring_info_get(const struct rte_event_timer_adapter
*adptr
,
44 struct rte_event_timer_adapter_info
*adptr_info
)
46 struct timvf_ring
*timr
= adptr
->data
->adapter_priv
;
47 adptr_info
->max_tmo_ns
= timr
->max_tout
;
48 adptr_info
->min_resolution_ns
= timr
->tck_nsec
;
49 rte_memcpy(&adptr_info
->conf
, &adptr
->data
->conf
,
50 sizeof(struct rte_event_timer_adapter_conf
));
54 timvf_ring_conf_set(struct timvf_ctrl_reg
*rctl
, uint8_t ring_id
)
56 struct octeontx_mbox_hdr hdr
= {0};
57 uint16_t len
= sizeof(struct timvf_ctrl_reg
);
60 hdr
.coproc
= TIM_COPROC
;
61 hdr
.msg
= TIM_SET_RING_INFO
;
64 ret
= octeontx_mbox_send(&hdr
, rctl
, len
, NULL
, 0);
65 if (ret
< 0 || hdr
.res_code
!= MBOX_RET_SUCCESS
)
71 timvf_get_start_cyc(uint64_t *now
, uint8_t ring_id
)
73 struct octeontx_mbox_hdr hdr
= {0};
75 hdr
.coproc
= TIM_COPROC
;
76 hdr
.msg
= TIM_RING_START_CYC_GET
;
79 return octeontx_mbox_send(&hdr
, NULL
, 0, now
, sizeof(uint64_t));
83 optimize_bucket_parameters(struct timvf_ring
*timr
)
89 hbkts
= rte_align32pow2(timr
->nb_bkts
);
90 tck_nsec
= RTE_ALIGN_MUL_CEIL(timr
->max_tout
/ (hbkts
- 1), 10);
92 if ((tck_nsec
< 1000 || hbkts
> TIM_MAX_BUCKETS
))
95 lbkts
= rte_align32prevpow2(timr
->nb_bkts
);
96 tck_nsec
= RTE_ALIGN_MUL_CEIL((timr
->max_tout
/ (lbkts
- 1)), 10);
98 if ((tck_nsec
< 1000 || hbkts
> TIM_MAX_BUCKETS
))
101 if (!hbkts
&& !lbkts
)
105 timr
->nb_bkts
= lbkts
;
108 timr
->nb_bkts
= hbkts
;
112 timr
->nb_bkts
= (hbkts
- timr
->nb_bkts
) <
113 (timr
->nb_bkts
- lbkts
) ? hbkts
: lbkts
;
115 timr
->get_target_bkt
= bkt_and
;
116 timr
->tck_nsec
= RTE_ALIGN_MUL_CEIL((timr
->max_tout
/
117 (timr
->nb_bkts
- 1)), 10);
122 timvf_ring_start(const struct rte_event_timer_adapter
*adptr
)
128 struct timvf_ctrl_reg rctrl
;
129 struct timvf_mbox_dev_info dinfo
;
130 struct timvf_ring
*timr
= adptr
->data
->adapter_priv
;
132 ret
= timvf_mbox_dev_info_get(&dinfo
);
133 if (ret
< 0 || ret
!= sizeof(struct timvf_mbox_dev_info
))
136 /* Calculate the interval cycles according to clock source. */
137 switch (timr
->clk_src
) {
138 case TIM_CLK_SRC_SCLK
:
139 interval
= NSEC2CLK(timr
->tck_nsec
, dinfo
.clk_freq
);
141 case TIM_CLK_SRC_GPIO
:
142 /* GPIO doesn't work on tck_nsec. */
145 case TIM_CLK_SRC_GTI
:
146 interval
= NSEC2CLK(timr
->tck_nsec
, dinfo
.clk_freq
);
148 case TIM_CLK_SRC_PTP
:
149 interval
= NSEC2CLK(timr
->tck_nsec
, dinfo
.clk_freq
);
152 timvf_log_err("Unsupported clock source configured %d",
157 if (!strcmp(rte_mbuf_best_mempool_ops(), "octeontx_fpavf"))
161 rctrl
.rctrl0
= interval
;
164 rctrl
.rctrl1
= (uint64_t)(timr
->clk_src
) << 51 |
165 1ull << 48 /* LOCK_EN (Enable hw bucket lock mechanism) */ |
166 1ull << 47 /* ENA */ |
167 1ull << 44 /* ENA_LDWB */ |
170 rctrl
.rctrl2
= (uint64_t)(TIM_CHUNK_SIZE
/ 16) << 40;
173 pool
= (uintptr_t)((struct rte_mempool
*)
174 timr
->chunk_pool
)->pool_id
;
175 ret
= octeontx_fpa_bufpool_gaura(pool
);
177 timvf_log_dbg("Unable to get gaura id");
181 timvf_write64((uint64_t)ret
,
182 (uint8_t *)timr
->vbar0
+ TIM_VRING_AURA
);
184 rctrl
.rctrl1
|= 1ull << 43 /* ENA_DFB (Enable don't free) */;
187 timvf_write64((uintptr_t)timr
->bkt
,
188 (uint8_t *)timr
->vbar0
+ TIM_VRING_BASE
);
189 timvf_set_chunk_refill(timr
, use_fpa
);
190 if (timvf_ring_conf_set(&rctrl
, timr
->tim_ring_id
)) {
195 if (timvf_get_start_cyc(&timr
->ring_start_cyc
,
196 timr
->tim_ring_id
) < 0) {
200 timr
->tck_int
= NSEC2CLK(timr
->tck_nsec
, rte_get_timer_hz());
201 timr
->fast_div
= rte_reciprocal_value_u64(timr
->tck_int
);
202 timvf_log_info("nb_bkts %d min_ns %"PRIu64
" min_cyc %"PRIu64
""
203 " maxtmo %"PRIu64
"\n",
204 timr
->nb_bkts
, timr
->tck_nsec
, interval
,
210 rte_mempool_free(timr
->chunk_pool
);
215 timvf_ring_stop(const struct rte_event_timer_adapter
*adptr
)
217 struct timvf_ring
*timr
= adptr
->data
->adapter_priv
;
218 struct timvf_ctrl_reg rctrl
= {0};
219 rctrl
.rctrl0
= timvf_read64((uint8_t *)timr
->vbar0
+ TIM_VRING_CTL0
);
220 rctrl
.rctrl1
= timvf_read64((uint8_t *)timr
->vbar0
+ TIM_VRING_CTL1
);
221 rctrl
.rctrl1
&= ~(1ull << 47); /* Disable */
222 rctrl
.rctrl2
= timvf_read64((uint8_t *)timr
->vbar0
+ TIM_VRING_CTL2
);
224 if (timvf_ring_conf_set(&rctrl
, timr
->tim_ring_id
))
230 timvf_ring_create(struct rte_event_timer_adapter
*adptr
)
236 struct rte_event_timer_adapter_conf
*rcfg
= &adptr
->data
->conf
;
237 struct timvf_ring
*timr
;
238 const char *mempool_ops
;
239 unsigned int mp_flags
= 0;
241 tim_ring_id
= timvf_get_ring();
242 if (tim_ring_id
== UINT8_MAX
)
245 timr
= rte_zmalloc("octeontx_timvf_priv",
246 sizeof(struct timvf_ring
), 0);
250 adptr
->data
->adapter_priv
= timr
;
251 /* Check config parameters. */
252 if ((rcfg
->clk_src
!= RTE_EVENT_TIMER_ADAPTER_CPU_CLK
) &&
253 (!rcfg
->timer_tick_ns
||
254 rcfg
->timer_tick_ns
< TIM_MIN_INTERVAL
)) {
255 timvf_log_err("Too low timer ticks");
259 timr
->clk_src
= (int) rcfg
->clk_src
;
260 timr
->tim_ring_id
= tim_ring_id
;
261 timr
->tck_nsec
= RTE_ALIGN_MUL_CEIL(rcfg
->timer_tick_ns
, 10);
262 timr
->max_tout
= rcfg
->max_tmo_ns
;
263 timr
->nb_bkts
= (timr
->max_tout
/ timr
->tck_nsec
);
264 timr
->vbar0
= timvf_bar(timr
->tim_ring_id
, 0);
265 timr
->bkt_pos
= (uint8_t *)timr
->vbar0
+ TIM_VRING_REL
;
266 nb_timers
= rcfg
->nb_timers
;
267 timr
->get_target_bkt
= bkt_mod
;
269 timr
->nb_chunks
= nb_timers
/ nb_chunk_slots
;
271 /* Try to optimize the bucket parameters. */
272 if ((rcfg
->flags
& RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES
)
273 && !rte_is_power_of_2(timr
->nb_bkts
)) {
274 if (optimize_bucket_parameters(timr
)) {
275 timvf_log_info("Optimized configured values");
276 timvf_log_dbg("nb_bkts : %"PRIu32
"", timr
->nb_bkts
);
277 timvf_log_dbg("tck_nsec : %"PRIu64
"", timr
->tck_nsec
);
279 timvf_log_info("Failed to Optimize configured values");
282 if (rcfg
->flags
& RTE_EVENT_TIMER_ADAPTER_F_SP_PUT
) {
283 mp_flags
= MEMPOOL_F_SP_PUT
| MEMPOOL_F_SC_GET
;
284 timvf_log_info("Using single producer mode");
287 timr
->bkt
= rte_zmalloc("octeontx_timvf_bucket",
288 (timr
->nb_bkts
) * sizeof(struct tim_mem_bucket
),
290 if (timr
->bkt
== NULL
)
293 snprintf(pool_name
, sizeof(pool_name
), "timvf_chunk_pool%d",
295 timr
->chunk_pool
= (void *)rte_mempool_create_empty(pool_name
,
296 timr
->nb_chunks
, TIM_CHUNK_SIZE
, 0, 0, rte_socket_id(),
299 if (!timr
->chunk_pool
) {
301 timvf_log_err("Unable to create chunkpool.");
305 mempool_ops
= rte_mbuf_best_mempool_ops();
306 ret
= rte_mempool_set_ops_byname(timr
->chunk_pool
,
310 timvf_log_err("Unable to set chunkpool ops.");
314 ret
= rte_mempool_populate_default(timr
->chunk_pool
);
316 timvf_log_err("Unable to set populate chunkpool.");
319 timvf_write64(0, (uint8_t *)timr
->vbar0
+ TIM_VRING_BASE
);
320 timvf_write64(0, (uint8_t *)timr
->vbar0
+ TIM_VF_NRSPERR_INT
);
321 timvf_write64(0, (uint8_t *)timr
->vbar0
+ TIM_VF_NRSPERR_INT_W1S
);
322 timvf_write64(0x7, (uint8_t *)timr
->vbar0
+ TIM_VF_NRSPERR_ENA_W1C
);
323 timvf_write64(0x7, (uint8_t *)timr
->vbar0
+ TIM_VF_NRSPERR_ENA_W1S
);
335 timvf_ring_free(struct rte_event_timer_adapter
*adptr
)
337 struct timvf_ring
*timr
= adptr
->data
->adapter_priv
;
339 rte_mempool_free(timr
->chunk_pool
);
341 timvf_release_ring(timr
->tim_ring_id
);
342 rte_free(adptr
->data
->adapter_priv
);
347 timvf_stats_get(const struct rte_event_timer_adapter
*adapter
,
348 struct rte_event_timer_adapter_stats
*stats
)
350 struct timvf_ring
*timr
= adapter
->data
->adapter_priv
;
351 uint64_t bkt_cyc
= rte_rdtsc() - timr
->ring_start_cyc
;
353 stats
->evtim_exp_count
= timr
->tim_arm_cnt
;
354 stats
->ev_enq_count
= timr
->tim_arm_cnt
;
355 stats
->adapter_tick_count
= rte_reciprocal_divide_u64(bkt_cyc
,
361 timvf_stats_reset(const struct rte_event_timer_adapter
*adapter
)
363 struct timvf_ring
*timr
= adapter
->data
->adapter_priv
;
365 timr
->tim_arm_cnt
= 0;
369 static struct rte_event_timer_adapter_ops timvf_ops
= {
370 .init
= timvf_ring_create
,
371 .uninit
= timvf_ring_free
,
372 .start
= timvf_ring_start
,
373 .stop
= timvf_ring_stop
,
374 .get_info
= timvf_ring_info_get
,
378 timvf_timer_adapter_caps_get(const struct rte_eventdev
*dev
, uint64_t flags
,
379 uint32_t *caps
, const struct rte_event_timer_adapter_ops
**ops
,
380 uint8_t enable_stats
)
385 timvf_ops
.stats_get
= timvf_stats_get
;
386 timvf_ops
.stats_reset
= timvf_stats_reset
;
389 if (flags
& RTE_EVENT_TIMER_ADAPTER_F_SP_PUT
)
390 timvf_ops
.arm_burst
= enable_stats
?
391 timvf_timer_arm_burst_sp_stats
:
392 timvf_timer_arm_burst_sp
;
394 timvf_ops
.arm_burst
= enable_stats
?
395 timvf_timer_arm_burst_mp_stats
:
396 timvf_timer_arm_burst_mp
;
398 timvf_ops
.arm_tmo_tick_burst
= enable_stats
?
399 timvf_timer_arm_tmo_brst_stats
:
400 timvf_timer_arm_tmo_brst
;
401 timvf_ops
.cancel_burst
= timvf_timer_cancel_burst
;
402 *caps
= RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT
;