xref: /dpdk/drivers/event/octeontx/timvf_evdev.c (revision e77506397fc8005c5129e22e9e2d15d5876790fd)
1db6a330bSPavan Nikhilesh /* SPDX-License-Identifier: BSD-3-Clause
2f874c1ebSPavan Nikhilesh  * Copyright(c) 2017 Cavium, Inc
3f874c1ebSPavan Nikhilesh  */
4f874c1ebSPavan Nikhilesh 
5227f2835SPavan Nikhilesh #include "ssovf_evdev.h"
6f874c1ebSPavan Nikhilesh #include "timvf_evdev.h"
7f874c1ebSPavan Nikhilesh 
8eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(otx_logtype_timvf, timer, NOTICE);
9f874c1ebSPavan Nikhilesh 
10227f2835SPavan Nikhilesh static struct rte_eventdev *event_dev;
11227f2835SPavan Nikhilesh 
12*e7750639SAndre Muezerie struct __rte_packed_begin timvf_mbox_dev_info {
13ea73fed2SPavan Nikhilesh 	uint64_t ring_active[4];
14ea73fed2SPavan Nikhilesh 	uint64_t clk_freq;
15*e7750639SAndre Muezerie } __rte_packed_end;
16ea73fed2SPavan Nikhilesh 
17ea73fed2SPavan Nikhilesh /* Response messages */
18ea73fed2SPavan Nikhilesh enum {
19ea73fed2SPavan Nikhilesh 	MBOX_RET_SUCCESS,
20ea73fed2SPavan Nikhilesh 	MBOX_RET_INVALID,
21ea73fed2SPavan Nikhilesh 	MBOX_RET_INTERNAL_ERR,
22ea73fed2SPavan Nikhilesh };
23ea73fed2SPavan Nikhilesh 
24ea73fed2SPavan Nikhilesh static int
25ea73fed2SPavan Nikhilesh timvf_mbox_dev_info_get(struct timvf_mbox_dev_info *info)
26ea73fed2SPavan Nikhilesh {
27ea73fed2SPavan Nikhilesh 	struct octeontx_mbox_hdr hdr = {0};
28ea73fed2SPavan Nikhilesh 	uint16_t len = sizeof(struct timvf_mbox_dev_info);
29ea73fed2SPavan Nikhilesh 
30ea73fed2SPavan Nikhilesh 	hdr.coproc = TIM_COPROC;
31ea73fed2SPavan Nikhilesh 	hdr.msg = TIM_GET_DEV_INFO;
32ea73fed2SPavan Nikhilesh 	hdr.vfid = 0; /* TIM DEV is always 0. TIM RING ID changes. */
33ea73fed2SPavan Nikhilesh 
34ea73fed2SPavan Nikhilesh 	memset(info, 0, len);
35ea73fed2SPavan Nikhilesh 	return octeontx_mbox_send(&hdr, NULL, 0, info, len);
36ea73fed2SPavan Nikhilesh }
37ea73fed2SPavan Nikhilesh 
38f874c1ebSPavan Nikhilesh static void
39f874c1ebSPavan Nikhilesh timvf_ring_info_get(const struct rte_event_timer_adapter *adptr,
40f874c1ebSPavan Nikhilesh 		struct rte_event_timer_adapter_info *adptr_info)
41f874c1ebSPavan Nikhilesh {
42f874c1ebSPavan Nikhilesh 	struct timvf_ring *timr = adptr->data->adapter_priv;
43f874c1ebSPavan Nikhilesh 	adptr_info->max_tmo_ns = timr->max_tout;
44f874c1ebSPavan Nikhilesh 	adptr_info->min_resolution_ns = timr->tck_nsec;
45f874c1ebSPavan Nikhilesh 	rte_memcpy(&adptr_info->conf, &adptr->data->conf,
46f874c1ebSPavan Nikhilesh 			sizeof(struct rte_event_timer_adapter_conf));
47f874c1ebSPavan Nikhilesh }
48f874c1ebSPavan Nikhilesh 
49f874c1ebSPavan Nikhilesh static int
50ea73fed2SPavan Nikhilesh timvf_ring_conf_set(struct timvf_ctrl_reg *rctl, uint8_t ring_id)
51ea73fed2SPavan Nikhilesh {
52ea73fed2SPavan Nikhilesh 	struct octeontx_mbox_hdr hdr = {0};
53ea73fed2SPavan Nikhilesh 	uint16_t len = sizeof(struct timvf_ctrl_reg);
54ea73fed2SPavan Nikhilesh 	int ret;
55ea73fed2SPavan Nikhilesh 
56ea73fed2SPavan Nikhilesh 	hdr.coproc = TIM_COPROC;
57ea73fed2SPavan Nikhilesh 	hdr.msg = TIM_SET_RING_INFO;
58ea73fed2SPavan Nikhilesh 	hdr.vfid = ring_id;
59ea73fed2SPavan Nikhilesh 
60ea73fed2SPavan Nikhilesh 	ret = octeontx_mbox_send(&hdr, rctl, len, NULL, 0);
61ea73fed2SPavan Nikhilesh 	if (ret < 0 || hdr.res_code != MBOX_RET_SUCCESS)
62ea73fed2SPavan Nikhilesh 		return -EACCES;
63ea73fed2SPavan Nikhilesh 	return 0;
64ea73fed2SPavan Nikhilesh }
65ea73fed2SPavan Nikhilesh 
66ea73fed2SPavan Nikhilesh static int
67ea73fed2SPavan Nikhilesh timvf_get_start_cyc(uint64_t *now, uint8_t ring_id)
68ea73fed2SPavan Nikhilesh {
69ea73fed2SPavan Nikhilesh 	struct octeontx_mbox_hdr hdr = {0};
70ea73fed2SPavan Nikhilesh 
71ea73fed2SPavan Nikhilesh 	hdr.coproc = TIM_COPROC;
72ea73fed2SPavan Nikhilesh 	hdr.msg = TIM_RING_START_CYC_GET;
73ea73fed2SPavan Nikhilesh 	hdr.vfid = ring_id;
74ea73fed2SPavan Nikhilesh 	*now = 0;
75ea73fed2SPavan Nikhilesh 	return octeontx_mbox_send(&hdr, NULL, 0, now, sizeof(uint64_t));
76ea73fed2SPavan Nikhilesh }
77ea73fed2SPavan Nikhilesh 
78ea73fed2SPavan Nikhilesh static int
794cec5aaeSPavan Nikhilesh optimize_bucket_parameters(struct timvf_ring *timr)
804cec5aaeSPavan Nikhilesh {
814cec5aaeSPavan Nikhilesh 	uint32_t hbkts;
824cec5aaeSPavan Nikhilesh 	uint32_t lbkts;
834cec5aaeSPavan Nikhilesh 	uint64_t tck_nsec;
844cec5aaeSPavan Nikhilesh 
854cec5aaeSPavan Nikhilesh 	hbkts = rte_align32pow2(timr->nb_bkts);
864cec5aaeSPavan Nikhilesh 	tck_nsec = RTE_ALIGN_MUL_CEIL(timr->max_tout / (hbkts - 1), 10);
874cec5aaeSPavan Nikhilesh 
884cec5aaeSPavan Nikhilesh 	if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
894cec5aaeSPavan Nikhilesh 		hbkts = 0;
904cec5aaeSPavan Nikhilesh 
914cec5aaeSPavan Nikhilesh 	lbkts = rte_align32prevpow2(timr->nb_bkts);
924cec5aaeSPavan Nikhilesh 	tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout / (lbkts - 1)), 10);
934cec5aaeSPavan Nikhilesh 
944cec5aaeSPavan Nikhilesh 	if ((tck_nsec < 1000 || hbkts > TIM_MAX_BUCKETS))
954cec5aaeSPavan Nikhilesh 		lbkts = 0;
964cec5aaeSPavan Nikhilesh 
974cec5aaeSPavan Nikhilesh 	if (!hbkts && !lbkts)
984cec5aaeSPavan Nikhilesh 		return 0;
994cec5aaeSPavan Nikhilesh 
1004cec5aaeSPavan Nikhilesh 	if (!hbkts) {
1014cec5aaeSPavan Nikhilesh 		timr->nb_bkts = lbkts;
1024cec5aaeSPavan Nikhilesh 		goto end;
1034cec5aaeSPavan Nikhilesh 	} else if (!lbkts) {
1044cec5aaeSPavan Nikhilesh 		timr->nb_bkts = hbkts;
1054cec5aaeSPavan Nikhilesh 		goto end;
1064cec5aaeSPavan Nikhilesh 	}
1074cec5aaeSPavan Nikhilesh 
1084cec5aaeSPavan Nikhilesh 	timr->nb_bkts = (hbkts - timr->nb_bkts) <
1094cec5aaeSPavan Nikhilesh 		(timr->nb_bkts - lbkts) ? hbkts : lbkts;
1104cec5aaeSPavan Nikhilesh end:
1114cec5aaeSPavan Nikhilesh 	timr->get_target_bkt = bkt_and;
1124cec5aaeSPavan Nikhilesh 	timr->tck_nsec = RTE_ALIGN_MUL_CEIL((timr->max_tout /
1134cec5aaeSPavan Nikhilesh 				(timr->nb_bkts - 1)), 10);
1144cec5aaeSPavan Nikhilesh 	return 1;
1154cec5aaeSPavan Nikhilesh }
1164cec5aaeSPavan Nikhilesh 
1174cec5aaeSPavan Nikhilesh static int
118ea73fed2SPavan Nikhilesh timvf_ring_start(const struct rte_event_timer_adapter *adptr)
119ea73fed2SPavan Nikhilesh {
120ea73fed2SPavan Nikhilesh 	int ret;
1213e249bc5SPavan Nikhilesh 	uint8_t use_fpa = 0;
122ea73fed2SPavan Nikhilesh 	uint64_t interval;
1233e249bc5SPavan Nikhilesh 	uintptr_t pool;
124ea73fed2SPavan Nikhilesh 	struct timvf_ctrl_reg rctrl;
125ea73fed2SPavan Nikhilesh 	struct timvf_mbox_dev_info dinfo;
126ea73fed2SPavan Nikhilesh 	struct timvf_ring *timr = adptr->data->adapter_priv;
127ea73fed2SPavan Nikhilesh 
128ea73fed2SPavan Nikhilesh 	ret = timvf_mbox_dev_info_get(&dinfo);
129ea73fed2SPavan Nikhilesh 	if (ret < 0 || ret != sizeof(struct timvf_mbox_dev_info))
130ea73fed2SPavan Nikhilesh 		return -EINVAL;
131ea73fed2SPavan Nikhilesh 
132ea73fed2SPavan Nikhilesh 	/* Calculate the interval cycles according to clock source. */
133ea73fed2SPavan Nikhilesh 	switch (timr->clk_src) {
134ea73fed2SPavan Nikhilesh 	case TIM_CLK_SRC_SCLK:
135ea73fed2SPavan Nikhilesh 		interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
136ea73fed2SPavan Nikhilesh 		break;
137ea73fed2SPavan Nikhilesh 	case TIM_CLK_SRC_GPIO:
138ea73fed2SPavan Nikhilesh 		/* GPIO doesn't work on tck_nsec. */
139ea73fed2SPavan Nikhilesh 		interval = 0;
140ea73fed2SPavan Nikhilesh 		break;
141ea73fed2SPavan Nikhilesh 	case TIM_CLK_SRC_GTI:
142ea73fed2SPavan Nikhilesh 		interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
143ea73fed2SPavan Nikhilesh 		break;
144ea73fed2SPavan Nikhilesh 	case TIM_CLK_SRC_PTP:
145ea73fed2SPavan Nikhilesh 		interval = NSEC2CLK(timr->tck_nsec, dinfo.clk_freq);
146ea73fed2SPavan Nikhilesh 		break;
147ea73fed2SPavan Nikhilesh 	default:
148ea73fed2SPavan Nikhilesh 		timvf_log_err("Unsupported clock source configured %d",
149ea73fed2SPavan Nikhilesh 				timr->clk_src);
150ea73fed2SPavan Nikhilesh 		return -EINVAL;
151ea73fed2SPavan Nikhilesh 	}
152ea73fed2SPavan Nikhilesh 
1533e249bc5SPavan Nikhilesh 	if (!strcmp(rte_mbuf_best_mempool_ops(), "octeontx_fpavf"))
1543e249bc5SPavan Nikhilesh 		use_fpa = 1;
1553e249bc5SPavan Nikhilesh 
156ea73fed2SPavan Nikhilesh 	/*CTRL0 register.*/
157ea73fed2SPavan Nikhilesh 	rctrl.rctrl0 = interval;
158ea73fed2SPavan Nikhilesh 
159ea73fed2SPavan Nikhilesh 	/*CTRL1	register.*/
160ea73fed2SPavan Nikhilesh 	rctrl.rctrl1 =	(uint64_t)(timr->clk_src) << 51 |
161ea73fed2SPavan Nikhilesh 		1ull << 48 /* LOCK_EN (Enable hw bucket lock mechanism) */ |
162ea73fed2SPavan Nikhilesh 		1ull << 47 /* ENA */ |
163ea73fed2SPavan Nikhilesh 		1ull << 44 /* ENA_LDWB */ |
164ea73fed2SPavan Nikhilesh 		(timr->nb_bkts - 1);
165ea73fed2SPavan Nikhilesh 
166ea73fed2SPavan Nikhilesh 	rctrl.rctrl2 = (uint64_t)(TIM_CHUNK_SIZE / 16) << 40;
167ea73fed2SPavan Nikhilesh 
1683e249bc5SPavan Nikhilesh 	if (use_fpa) {
1693e249bc5SPavan Nikhilesh 		pool = (uintptr_t)((struct rte_mempool *)
1703e249bc5SPavan Nikhilesh 				timr->chunk_pool)->pool_id;
171179c7e89SPavan Nikhilesh 		ret = octeontx_fpa_bufpool_gaura(pool);
1723e249bc5SPavan Nikhilesh 		if (ret < 0) {
1733e249bc5SPavan Nikhilesh 			timvf_log_dbg("Unable to get gaura id");
1743e249bc5SPavan Nikhilesh 			ret = -ENOMEM;
1753e249bc5SPavan Nikhilesh 			goto error;
1763e249bc5SPavan Nikhilesh 		}
1773e249bc5SPavan Nikhilesh 		timvf_write64((uint64_t)ret,
1783e249bc5SPavan Nikhilesh 				(uint8_t *)timr->vbar0 + TIM_VRING_AURA);
1793e249bc5SPavan Nikhilesh 	} else {
1803e249bc5SPavan Nikhilesh 		rctrl.rctrl1 |= 1ull << 43 /* ENA_DFB (Enable don't free) */;
1813e249bc5SPavan Nikhilesh 	}
1823e249bc5SPavan Nikhilesh 
183ea73fed2SPavan Nikhilesh 	timvf_write64((uintptr_t)timr->bkt,
184ea73fed2SPavan Nikhilesh 			(uint8_t *)timr->vbar0 + TIM_VRING_BASE);
1853e249bc5SPavan Nikhilesh 	timvf_set_chunk_refill(timr, use_fpa);
186ea73fed2SPavan Nikhilesh 	if (timvf_ring_conf_set(&rctrl, timr->tim_ring_id)) {
187ea73fed2SPavan Nikhilesh 		ret = -EACCES;
188ea73fed2SPavan Nikhilesh 		goto error;
189ea73fed2SPavan Nikhilesh 	}
190ea73fed2SPavan Nikhilesh 
191ea73fed2SPavan Nikhilesh 	if (timvf_get_start_cyc(&timr->ring_start_cyc,
192ea73fed2SPavan Nikhilesh 				timr->tim_ring_id) < 0) {
193ea73fed2SPavan Nikhilesh 		ret = -EACCES;
194ea73fed2SPavan Nikhilesh 		goto error;
195ea73fed2SPavan Nikhilesh 	}
196ea73fed2SPavan Nikhilesh 	timr->tck_int = NSEC2CLK(timr->tck_nsec, rte_get_timer_hz());
197ea73fed2SPavan Nikhilesh 	timr->fast_div = rte_reciprocal_value_u64(timr->tck_int);
198ea73fed2SPavan Nikhilesh 	timvf_log_info("nb_bkts %d min_ns %"PRIu64" min_cyc %"PRIu64""
199f665790aSDavid Marchand 			" maxtmo %"PRIu64,
200ea73fed2SPavan Nikhilesh 			timr->nb_bkts, timr->tck_nsec, interval,
201ea73fed2SPavan Nikhilesh 			timr->max_tout);
202ea73fed2SPavan Nikhilesh 
203ea73fed2SPavan Nikhilesh 	return 0;
204ea73fed2SPavan Nikhilesh error:
205ea73fed2SPavan Nikhilesh 	rte_free(timr->bkt);
206ea73fed2SPavan Nikhilesh 	rte_mempool_free(timr->chunk_pool);
207ea73fed2SPavan Nikhilesh 	return ret;
208ea73fed2SPavan Nikhilesh }
209ea73fed2SPavan Nikhilesh 
210ea73fed2SPavan Nikhilesh static int
211ea73fed2SPavan Nikhilesh timvf_ring_stop(const struct rte_event_timer_adapter *adptr)
212ea73fed2SPavan Nikhilesh {
213ea73fed2SPavan Nikhilesh 	struct timvf_ring *timr = adptr->data->adapter_priv;
214ea73fed2SPavan Nikhilesh 	struct timvf_ctrl_reg rctrl = {0};
215ea73fed2SPavan Nikhilesh 	rctrl.rctrl0 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL0);
216ea73fed2SPavan Nikhilesh 	rctrl.rctrl1 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL1);
217ea73fed2SPavan Nikhilesh 	rctrl.rctrl1 &= ~(1ull << 47); /* Disable */
218ea73fed2SPavan Nikhilesh 	rctrl.rctrl2 = timvf_read64((uint8_t *)timr->vbar0 + TIM_VRING_CTL2);
219ea73fed2SPavan Nikhilesh 
220ea73fed2SPavan Nikhilesh 	if (timvf_ring_conf_set(&rctrl, timr->tim_ring_id))
221ea73fed2SPavan Nikhilesh 		return -EACCES;
222ea73fed2SPavan Nikhilesh 	return 0;
223ea73fed2SPavan Nikhilesh }
224ea73fed2SPavan Nikhilesh 
225ea73fed2SPavan Nikhilesh static int
226f874c1ebSPavan Nikhilesh timvf_ring_create(struct rte_event_timer_adapter *adptr)
227f874c1ebSPavan Nikhilesh {
228f874c1ebSPavan Nikhilesh 	struct rte_event_timer_adapter_conf *rcfg = &adptr->data->conf;
229227f2835SPavan Nikhilesh 	uint16_t free_idx = UINT16_MAX;
230227f2835SPavan Nikhilesh 	unsigned int mp_flags = 0;
231227f2835SPavan Nikhilesh 	struct ssovf_evdev *edev;
232f874c1ebSPavan Nikhilesh 	struct timvf_ring *timr;
233f874c1ebSPavan Nikhilesh 	const char *mempool_ops;
234227f2835SPavan Nikhilesh 	uint8_t tim_ring_id;
235227f2835SPavan Nikhilesh 	char pool_name[25];
236227f2835SPavan Nikhilesh 	int i, ret;
237f874c1ebSPavan Nikhilesh 
2383639b4adSPavan Nikhilesh 	tim_ring_id = timvf_get_ring();
2393639b4adSPavan Nikhilesh 	if (tim_ring_id == UINT8_MAX)
240f874c1ebSPavan Nikhilesh 		return -ENODEV;
241f874c1ebSPavan Nikhilesh 
242227f2835SPavan Nikhilesh 	edev = ssovf_pmd_priv(event_dev);
243f874c1ebSPavan Nikhilesh 	timr = rte_zmalloc("octeontx_timvf_priv",
244f874c1ebSPavan Nikhilesh 			sizeof(struct timvf_ring), 0);
245f874c1ebSPavan Nikhilesh 	if (timr == NULL)
246f874c1ebSPavan Nikhilesh 		return -ENOMEM;
247f874c1ebSPavan Nikhilesh 
248f874c1ebSPavan Nikhilesh 	adptr->data->adapter_priv = timr;
249f874c1ebSPavan Nikhilesh 	/* Check config parameters. */
250f874c1ebSPavan Nikhilesh 	if ((rcfg->clk_src != RTE_EVENT_TIMER_ADAPTER_CPU_CLK) &&
251f874c1ebSPavan Nikhilesh 			(!rcfg->timer_tick_ns ||
252f874c1ebSPavan Nikhilesh 			 rcfg->timer_tick_ns < TIM_MIN_INTERVAL)) {
253f874c1ebSPavan Nikhilesh 		timvf_log_err("Too low timer ticks");
254f874c1ebSPavan Nikhilesh 		goto cfg_err;
255f874c1ebSPavan Nikhilesh 	}
256f874c1ebSPavan Nikhilesh 
257f874c1ebSPavan Nikhilesh 	timr->clk_src = (int) rcfg->clk_src;
2583639b4adSPavan Nikhilesh 	timr->tim_ring_id = tim_ring_id;
2594cec5aaeSPavan Nikhilesh 	timr->tck_nsec = RTE_ALIGN_MUL_CEIL(rcfg->timer_tick_ns, 10);
260f874c1ebSPavan Nikhilesh 	timr->max_tout = rcfg->max_tmo_ns;
261f874c1ebSPavan Nikhilesh 	timr->nb_bkts = (timr->max_tout / timr->tck_nsec);
262f874c1ebSPavan Nikhilesh 	timr->vbar0 = timvf_bar(timr->tim_ring_id, 0);
263f874c1ebSPavan Nikhilesh 	timr->bkt_pos = (uint8_t *)timr->vbar0 + TIM_VRING_REL;
264227f2835SPavan Nikhilesh 	timr->nb_timers = rcfg->nb_timers;
265f874c1ebSPavan Nikhilesh 	timr->get_target_bkt = bkt_mod;
266f874c1ebSPavan Nikhilesh 
267227f2835SPavan Nikhilesh 	if (edev->available_events < timr->nb_timers) {
268227f2835SPavan Nikhilesh 		timvf_log_err(
269227f2835SPavan Nikhilesh 			"Max available events %"PRIu32" requested timer events %"PRIu64"",
270227f2835SPavan Nikhilesh 			edev->available_events, timr->nb_timers);
271227f2835SPavan Nikhilesh 		return -ENOMEM;
272227f2835SPavan Nikhilesh 	}
273227f2835SPavan Nikhilesh 
274227f2835SPavan Nikhilesh 	for (i = 0; i < edev->tim_ring_cnt; i++) {
275227f2835SPavan Nikhilesh 		if (edev->tim_ring_ids[i] == UINT16_MAX)
276227f2835SPavan Nikhilesh 			free_idx = i;
277227f2835SPavan Nikhilesh 	}
278227f2835SPavan Nikhilesh 
279227f2835SPavan Nikhilesh 	if (free_idx == UINT16_MAX) {
280227f2835SPavan Nikhilesh 		void *old_ptr;
281227f2835SPavan Nikhilesh 
282227f2835SPavan Nikhilesh 		edev->tim_ring_cnt++;
283227f2835SPavan Nikhilesh 		old_ptr = edev->tim_ring_ids;
284227f2835SPavan Nikhilesh 		edev->tim_ring_ids =
285227f2835SPavan Nikhilesh 			rte_realloc(edev->tim_ring_ids,
286227f2835SPavan Nikhilesh 				    sizeof(uint16_t) * edev->tim_ring_cnt, 0);
287227f2835SPavan Nikhilesh 		if (edev->tim_ring_ids == NULL) {
288227f2835SPavan Nikhilesh 			edev->tim_ring_ids = old_ptr;
289227f2835SPavan Nikhilesh 			edev->tim_ring_cnt--;
290227f2835SPavan Nikhilesh 			return -ENOMEM;
291227f2835SPavan Nikhilesh 		}
292227f2835SPavan Nikhilesh 
293227f2835SPavan Nikhilesh 		edev->available_events -= timr->nb_timers;
294227f2835SPavan Nikhilesh 	} else {
295227f2835SPavan Nikhilesh 		edev->tim_ring_ids[free_idx] = tim_ring_id;
296227f2835SPavan Nikhilesh 		edev->available_events -= timr->nb_timers;
297227f2835SPavan Nikhilesh 	}
298227f2835SPavan Nikhilesh 
299227f2835SPavan Nikhilesh 	timr->nb_chunks = timr->nb_timers / nb_chunk_slots;
300f874c1ebSPavan Nikhilesh 
3014cec5aaeSPavan Nikhilesh 	/* Try to optimize the bucket parameters. */
3024cec5aaeSPavan Nikhilesh 	if ((rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES)
3034cec5aaeSPavan Nikhilesh 			&& !rte_is_power_of_2(timr->nb_bkts)) {
3044cec5aaeSPavan Nikhilesh 		if (optimize_bucket_parameters(timr)) {
3054cec5aaeSPavan Nikhilesh 			timvf_log_info("Optimized configured values");
3064cec5aaeSPavan Nikhilesh 			timvf_log_dbg("nb_bkts  : %"PRIu32"", timr->nb_bkts);
3074cec5aaeSPavan Nikhilesh 			timvf_log_dbg("tck_nsec : %"PRIu64"", timr->tck_nsec);
3084cec5aaeSPavan Nikhilesh 		} else
3094cec5aaeSPavan Nikhilesh 			timvf_log_info("Failed to Optimize configured values");
3104cec5aaeSPavan Nikhilesh 	}
3114cec5aaeSPavan Nikhilesh 
3127684fcf1SPavan Nikhilesh 	if (rcfg->flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT) {
313c47d7b90SAndrew Rybchenko 		mp_flags = RTE_MEMPOOL_F_SP_PUT | RTE_MEMPOOL_F_SC_GET;
3147684fcf1SPavan Nikhilesh 		timvf_log_info("Using single producer mode");
3157684fcf1SPavan Nikhilesh 	}
3167684fcf1SPavan Nikhilesh 
317f874c1ebSPavan Nikhilesh 	timr->bkt = rte_zmalloc("octeontx_timvf_bucket",
318f874c1ebSPavan Nikhilesh 			(timr->nb_bkts) * sizeof(struct tim_mem_bucket),
319f874c1ebSPavan Nikhilesh 			0);
320f874c1ebSPavan Nikhilesh 	if (timr->bkt == NULL)
321f874c1ebSPavan Nikhilesh 		goto mem_err;
322f874c1ebSPavan Nikhilesh 
32313573bd3SPavan Nikhilesh 	snprintf(pool_name, sizeof(pool_name), "timvf_chunk_pool%d",
32413573bd3SPavan Nikhilesh 			timr->tim_ring_id);
325f874c1ebSPavan Nikhilesh 	timr->chunk_pool = (void *)rte_mempool_create_empty(pool_name,
326f874c1ebSPavan Nikhilesh 			timr->nb_chunks, TIM_CHUNK_SIZE, 0, 0, rte_socket_id(),
3277684fcf1SPavan Nikhilesh 			mp_flags);
328f874c1ebSPavan Nikhilesh 
329f874c1ebSPavan Nikhilesh 	if (!timr->chunk_pool) {
330f874c1ebSPavan Nikhilesh 		rte_free(timr->bkt);
331f874c1ebSPavan Nikhilesh 		timvf_log_err("Unable to create chunkpool.");
332f874c1ebSPavan Nikhilesh 		return -ENOMEM;
333f874c1ebSPavan Nikhilesh 	}
334f874c1ebSPavan Nikhilesh 
335f874c1ebSPavan Nikhilesh 	mempool_ops = rte_mbuf_best_mempool_ops();
336f874c1ebSPavan Nikhilesh 	ret = rte_mempool_set_ops_byname(timr->chunk_pool,
337f874c1ebSPavan Nikhilesh 			mempool_ops, NULL);
338f874c1ebSPavan Nikhilesh 
339f874c1ebSPavan Nikhilesh 	if (ret != 0) {
340f874c1ebSPavan Nikhilesh 		timvf_log_err("Unable to set chunkpool ops.");
341f874c1ebSPavan Nikhilesh 		goto mem_err;
342f874c1ebSPavan Nikhilesh 	}
343f874c1ebSPavan Nikhilesh 
344f874c1ebSPavan Nikhilesh 	ret = rte_mempool_populate_default(timr->chunk_pool);
345f874c1ebSPavan Nikhilesh 	if (ret < 0) {
346f874c1ebSPavan Nikhilesh 		timvf_log_err("Unable to set populate chunkpool.");
347f874c1ebSPavan Nikhilesh 		goto mem_err;
348f874c1ebSPavan Nikhilesh 	}
349f874c1ebSPavan Nikhilesh 	timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VRING_BASE);
350f874c1ebSPavan Nikhilesh 	timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_INT);
351f874c1ebSPavan Nikhilesh 	timvf_write64(0, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_INT_W1S);
352f874c1ebSPavan Nikhilesh 	timvf_write64(0x7, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_ENA_W1C);
353f874c1ebSPavan Nikhilesh 	timvf_write64(0x7, (uint8_t *)timr->vbar0 + TIM_VF_NRSPERR_ENA_W1S);
354f874c1ebSPavan Nikhilesh 
355f874c1ebSPavan Nikhilesh 	return 0;
356f874c1ebSPavan Nikhilesh mem_err:
357f874c1ebSPavan Nikhilesh 	rte_free(timr);
358f874c1ebSPavan Nikhilesh 	return -ENOMEM;
359f874c1ebSPavan Nikhilesh cfg_err:
360f874c1ebSPavan Nikhilesh 	rte_free(timr);
361f874c1ebSPavan Nikhilesh 	return -EINVAL;
362f874c1ebSPavan Nikhilesh }
363f874c1ebSPavan Nikhilesh 
364f874c1ebSPavan Nikhilesh static int
365f874c1ebSPavan Nikhilesh timvf_ring_free(struct rte_event_timer_adapter *adptr)
366f874c1ebSPavan Nikhilesh {
367f874c1ebSPavan Nikhilesh 	struct timvf_ring *timr = adptr->data->adapter_priv;
368227f2835SPavan Nikhilesh 	struct ssovf_evdev *edev;
369227f2835SPavan Nikhilesh 	int i;
370227f2835SPavan Nikhilesh 
371227f2835SPavan Nikhilesh 	edev = ssovf_pmd_priv(event_dev);
372227f2835SPavan Nikhilesh 	for (i = 0; i < edev->tim_ring_cnt; i++) {
373227f2835SPavan Nikhilesh 		if (edev->tim_ring_ids[i] == timr->tim_ring_id) {
374227f2835SPavan Nikhilesh 			edev->available_events += timr->nb_timers;
375227f2835SPavan Nikhilesh 			edev->tim_ring_ids[i] = UINT16_MAX;
376227f2835SPavan Nikhilesh 			break;
377227f2835SPavan Nikhilesh 		}
378227f2835SPavan Nikhilesh 	}
3793639b4adSPavan Nikhilesh 
380f874c1ebSPavan Nikhilesh 	rte_mempool_free(timr->chunk_pool);
381f874c1ebSPavan Nikhilesh 	rte_free(timr->bkt);
3823639b4adSPavan Nikhilesh 	timvf_release_ring(timr->tim_ring_id);
383f874c1ebSPavan Nikhilesh 	rte_free(adptr->data->adapter_priv);
384f874c1ebSPavan Nikhilesh 	return 0;
385f874c1ebSPavan Nikhilesh }
386f874c1ebSPavan Nikhilesh 
387d1925c87SPavan Nikhilesh static int
388d1925c87SPavan Nikhilesh timvf_stats_get(const struct rte_event_timer_adapter *adapter,
389d1925c87SPavan Nikhilesh 		struct rte_event_timer_adapter_stats *stats)
390d1925c87SPavan Nikhilesh {
391d1925c87SPavan Nikhilesh 	struct timvf_ring *timr = adapter->data->adapter_priv;
392d1925c87SPavan Nikhilesh 	uint64_t bkt_cyc = rte_rdtsc() - timr->ring_start_cyc;
393d1925c87SPavan Nikhilesh 
394d1925c87SPavan Nikhilesh 	stats->evtim_exp_count = timr->tim_arm_cnt;
395d1925c87SPavan Nikhilesh 	stats->ev_enq_count = timr->tim_arm_cnt;
396d1925c87SPavan Nikhilesh 	stats->adapter_tick_count = rte_reciprocal_divide_u64(bkt_cyc,
397d1925c87SPavan Nikhilesh 				&timr->fast_div);
398d1925c87SPavan Nikhilesh 	return 0;
399d1925c87SPavan Nikhilesh }
400d1925c87SPavan Nikhilesh 
401d1925c87SPavan Nikhilesh static int
402d1925c87SPavan Nikhilesh timvf_stats_reset(const struct rte_event_timer_adapter *adapter)
403d1925c87SPavan Nikhilesh {
404d1925c87SPavan Nikhilesh 	struct timvf_ring *timr = adapter->data->adapter_priv;
405d1925c87SPavan Nikhilesh 
406d1925c87SPavan Nikhilesh 	timr->tim_arm_cnt = 0;
407d1925c87SPavan Nikhilesh 	return 0;
408d1925c87SPavan Nikhilesh }
409d1925c87SPavan Nikhilesh 
41053548ad3SPavan Nikhilesh static struct event_timer_adapter_ops timvf_ops = {
411f874c1ebSPavan Nikhilesh 	.init = timvf_ring_create,
412f874c1ebSPavan Nikhilesh 	.uninit = timvf_ring_free,
413ea73fed2SPavan Nikhilesh 	.start = timvf_ring_start,
414ea73fed2SPavan Nikhilesh 	.stop = timvf_ring_stop,
415f874c1ebSPavan Nikhilesh 	.get_info = timvf_ring_info_get,
416f874c1ebSPavan Nikhilesh };
417f874c1ebSPavan Nikhilesh 
418f874c1ebSPavan Nikhilesh int
419f874c1ebSPavan Nikhilesh timvf_timer_adapter_caps_get(const struct rte_eventdev *dev, uint64_t flags,
42053548ad3SPavan Nikhilesh 			     uint32_t *caps,
42153548ad3SPavan Nikhilesh 			     const struct event_timer_adapter_ops **ops,
422f874c1ebSPavan Nikhilesh 			     uint8_t enable_stats)
423f874c1ebSPavan Nikhilesh {
424f874c1ebSPavan Nikhilesh 	RTE_SET_USED(dev);
425d1925c87SPavan Nikhilesh 
426d1925c87SPavan Nikhilesh 	if (enable_stats) {
427d1925c87SPavan Nikhilesh 		timvf_ops.stats_get   = timvf_stats_get;
428d1925c87SPavan Nikhilesh 		timvf_ops.stats_reset = timvf_stats_reset;
429d1925c87SPavan Nikhilesh 	}
430d1925c87SPavan Nikhilesh 
4317684fcf1SPavan Nikhilesh 	if (flags & RTE_EVENT_TIMER_ADAPTER_F_SP_PUT)
4327684fcf1SPavan Nikhilesh 		timvf_ops.arm_burst = enable_stats ?
4337684fcf1SPavan Nikhilesh 			timvf_timer_arm_burst_sp_stats :
4347684fcf1SPavan Nikhilesh 			timvf_timer_arm_burst_sp;
435b6d814d8SPavan Nikhilesh 	else
4367684fcf1SPavan Nikhilesh 		timvf_ops.arm_burst = enable_stats ?
4377684fcf1SPavan Nikhilesh 			timvf_timer_arm_burst_mp_stats :
4387684fcf1SPavan Nikhilesh 			timvf_timer_arm_burst_mp;
439b6d814d8SPavan Nikhilesh 
4400896f7e0SPavan Nikhilesh 	timvf_ops.arm_tmo_tick_burst = enable_stats ?
4410896f7e0SPavan Nikhilesh 		timvf_timer_arm_tmo_brst_stats :
4420896f7e0SPavan Nikhilesh 		timvf_timer_arm_tmo_brst;
443b6d814d8SPavan Nikhilesh 	timvf_ops.cancel_burst = timvf_timer_cancel_burst;
444f874c1ebSPavan Nikhilesh 	*caps = RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT;
445f874c1ebSPavan Nikhilesh 	*ops = &timvf_ops;
446b6d814d8SPavan Nikhilesh 	return 0;
447f874c1ebSPavan Nikhilesh }
448227f2835SPavan Nikhilesh 
449227f2835SPavan Nikhilesh void
450227f2835SPavan Nikhilesh timvf_set_eventdevice(struct rte_eventdev *dev)
451227f2835SPavan Nikhilesh {
452227f2835SPavan Nikhilesh 	event_dev = dev;
453227f2835SPavan Nikhilesh }
454