xref: /dpdk/lib/eventdev/rte_event_timer_adapter.c (revision af0785a2447b307965377b62f46a5f39457a85a3)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2017-2018 Intel Corporation.
399a2dd95SBruce Richardson  * All rights reserved.
499a2dd95SBruce Richardson  */
599a2dd95SBruce Richardson 
672b452c5SDmitry Kozlyuk #include <ctype.h>
799a2dd95SBruce Richardson #include <string.h>
899a2dd95SBruce Richardson #include <inttypes.h>
999a2dd95SBruce Richardson #include <stdbool.h>
1072b452c5SDmitry Kozlyuk #include <stdlib.h>
110727ff34SErik Gabriel Carrillo #include <math.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include <rte_memzone.h>
1499a2dd95SBruce Richardson #include <rte_errno.h>
1599a2dd95SBruce Richardson #include <rte_malloc.h>
1699a2dd95SBruce Richardson #include <rte_mempool.h>
1799a2dd95SBruce Richardson #include <rte_common.h>
1899a2dd95SBruce Richardson #include <rte_timer.h>
1999a2dd95SBruce Richardson #include <rte_service_component.h>
20791dfec2SAnkur Dwivedi #include <rte_telemetry.h>
2199a2dd95SBruce Richardson 
2253548ad3SPavan Nikhilesh #include "event_timer_adapter_pmd.h"
2399a2dd95SBruce Richardson #include "eventdev_pmd.h"
2499a2dd95SBruce Richardson #include "rte_event_timer_adapter.h"
2553548ad3SPavan Nikhilesh #include "rte_eventdev.h"
26f26f2ca6SPavan Nikhilesh #include "eventdev_trace.h"
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson #define DATA_MZ_NAME_MAX_LEN 64
2999a2dd95SBruce Richardson #define DATA_MZ_NAME_FORMAT "rte_event_timer_adapter_data_%d"
3099a2dd95SBruce Richardson 
31eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_logtype, adapter.timer, NOTICE);
32eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_buffer_logtype, adapter.timer, NOTICE);
33eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_svc_logtype, adapter.timer.svc, NOTICE);
3499a2dd95SBruce Richardson 
35f3f3a917SPavan Nikhilesh static struct rte_event_timer_adapter *adapters;
3699a2dd95SBruce Richardson 
3753548ad3SPavan Nikhilesh static const struct event_timer_adapter_ops swtim_ops;
3899a2dd95SBruce Richardson 
3999a2dd95SBruce Richardson #define EVTIM_LOG(level, logtype, ...) \
4099a2dd95SBruce Richardson 	rte_log(RTE_LOG_ ## level, logtype, \
4199a2dd95SBruce Richardson 		RTE_FMT("EVTIMER: %s() line %u: " RTE_FMT_HEAD(__VA_ARGS__,) \
4299a2dd95SBruce Richardson 			"\n", __func__, __LINE__, RTE_FMT_TAIL(__VA_ARGS__,)))
4399a2dd95SBruce Richardson 
4499a2dd95SBruce Richardson #define EVTIM_LOG_ERR(...) EVTIM_LOG(ERR, evtim_logtype, __VA_ARGS__)
4599a2dd95SBruce Richardson 
4699a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
4799a2dd95SBruce Richardson #define EVTIM_LOG_DBG(...) \
4899a2dd95SBruce Richardson 	EVTIM_LOG(DEBUG, evtim_logtype, __VA_ARGS__)
4999a2dd95SBruce Richardson #define EVTIM_BUF_LOG_DBG(...) \
5099a2dd95SBruce Richardson 	EVTIM_LOG(DEBUG, evtim_buffer_logtype, __VA_ARGS__)
5199a2dd95SBruce Richardson #define EVTIM_SVC_LOG_DBG(...) \
5299a2dd95SBruce Richardson 	EVTIM_LOG(DEBUG, evtim_svc_logtype, __VA_ARGS__)
5399a2dd95SBruce Richardson #else
5499a2dd95SBruce Richardson #define EVTIM_LOG_DBG(...) (void)0
5599a2dd95SBruce Richardson #define EVTIM_BUF_LOG_DBG(...) (void)0
5699a2dd95SBruce Richardson #define EVTIM_SVC_LOG_DBG(...) (void)0
5799a2dd95SBruce Richardson #endif
5899a2dd95SBruce Richardson 
593d9d8adfSNaga Harish K S V static inline enum rte_timer_type
603d9d8adfSNaga Harish K S V get_timer_type(const struct rte_event_timer_adapter *adapter)
613d9d8adfSNaga Harish K S V {
623d9d8adfSNaga Harish K S V 	return (adapter->data->conf.flags &
633d9d8adfSNaga Harish K S V 			RTE_EVENT_TIMER_ADAPTER_F_PERIODIC) ?
643d9d8adfSNaga Harish K S V 			PERIODICAL : SINGLE;
653d9d8adfSNaga Harish K S V }
663d9d8adfSNaga Harish K S V 
6799a2dd95SBruce Richardson static int
6899a2dd95SBruce Richardson default_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id,
6999a2dd95SBruce Richardson 		     void *conf_arg)
7099a2dd95SBruce Richardson {
7199a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter;
7299a2dd95SBruce Richardson 	struct rte_eventdev *dev;
7399a2dd95SBruce Richardson 	struct rte_event_dev_config dev_conf;
7499a2dd95SBruce Richardson 	struct rte_event_port_conf *port_conf, def_port_conf = {0};
7599a2dd95SBruce Richardson 	int started;
7699a2dd95SBruce Richardson 	uint8_t port_id;
7799a2dd95SBruce Richardson 	uint8_t dev_id;
7899a2dd95SBruce Richardson 	int ret;
7999a2dd95SBruce Richardson 
8099a2dd95SBruce Richardson 	RTE_SET_USED(event_dev_id);
8199a2dd95SBruce Richardson 
8299a2dd95SBruce Richardson 	adapter = &adapters[id];
8399a2dd95SBruce Richardson 	dev = &rte_eventdevs[adapter->data->event_dev_id];
8499a2dd95SBruce Richardson 	dev_id = dev->data->dev_id;
8599a2dd95SBruce Richardson 	dev_conf = dev->data->dev_conf;
8699a2dd95SBruce Richardson 
8799a2dd95SBruce Richardson 	started = dev->data->dev_started;
8899a2dd95SBruce Richardson 	if (started)
8999a2dd95SBruce Richardson 		rte_event_dev_stop(dev_id);
9099a2dd95SBruce Richardson 
9199a2dd95SBruce Richardson 	port_id = dev_conf.nb_event_ports;
92850ae162SNaga Harish K S V 	if (conf_arg != NULL)
93850ae162SNaga Harish K S V 		port_conf = conf_arg;
94850ae162SNaga Harish K S V 	else {
95850ae162SNaga Harish K S V 		port_conf = &def_port_conf;
96850ae162SNaga Harish K S V 		ret = rte_event_port_default_conf_get(dev_id, (port_id - 1),
97850ae162SNaga Harish K S V 						      port_conf);
98850ae162SNaga Harish K S V 		if (ret < 0)
99850ae162SNaga Harish K S V 			return ret;
100850ae162SNaga Harish K S V 	}
101850ae162SNaga Harish K S V 
10299a2dd95SBruce Richardson 	dev_conf.nb_event_ports += 1;
103850ae162SNaga Harish K S V 	if (port_conf->event_port_cfg & RTE_EVENT_PORT_CFG_SINGLE_LINK)
104850ae162SNaga Harish K S V 		dev_conf.nb_single_link_event_port_queues += 1;
105850ae162SNaga Harish K S V 
10699a2dd95SBruce Richardson 	ret = rte_event_dev_configure(dev_id, &dev_conf);
10799a2dd95SBruce Richardson 	if (ret < 0) {
10899a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to configure event dev %u\n", dev_id);
10999a2dd95SBruce Richardson 		if (started)
11099a2dd95SBruce Richardson 			if (rte_event_dev_start(dev_id))
11199a2dd95SBruce Richardson 				return -EIO;
11299a2dd95SBruce Richardson 
11399a2dd95SBruce Richardson 		return ret;
11499a2dd95SBruce Richardson 	}
11599a2dd95SBruce Richardson 
11699a2dd95SBruce Richardson 	ret = rte_event_port_setup(dev_id, port_id, port_conf);
11799a2dd95SBruce Richardson 	if (ret < 0) {
11899a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to setup event port %u on event dev %u\n",
11999a2dd95SBruce Richardson 			      port_id, dev_id);
12099a2dd95SBruce Richardson 		return ret;
12199a2dd95SBruce Richardson 	}
12299a2dd95SBruce Richardson 
12399a2dd95SBruce Richardson 	*event_port_id = port_id;
12499a2dd95SBruce Richardson 
12599a2dd95SBruce Richardson 	if (started)
12699a2dd95SBruce Richardson 		ret = rte_event_dev_start(dev_id);
12799a2dd95SBruce Richardson 
12899a2dd95SBruce Richardson 	return ret;
12999a2dd95SBruce Richardson }
13099a2dd95SBruce Richardson 
13199a2dd95SBruce Richardson struct rte_event_timer_adapter *
13299a2dd95SBruce Richardson rte_event_timer_adapter_create(const struct rte_event_timer_adapter_conf *conf)
13399a2dd95SBruce Richardson {
13499a2dd95SBruce Richardson 	return rte_event_timer_adapter_create_ext(conf, default_port_conf_cb,
13599a2dd95SBruce Richardson 						  NULL);
13699a2dd95SBruce Richardson }
13799a2dd95SBruce Richardson 
13899a2dd95SBruce Richardson struct rte_event_timer_adapter *
13999a2dd95SBruce Richardson rte_event_timer_adapter_create_ext(
14099a2dd95SBruce Richardson 		const struct rte_event_timer_adapter_conf *conf,
14199a2dd95SBruce Richardson 		rte_event_timer_adapter_port_conf_cb_t conf_cb,
14299a2dd95SBruce Richardson 		void *conf_arg)
14399a2dd95SBruce Richardson {
14499a2dd95SBruce Richardson 	uint16_t adapter_id;
14599a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter;
14699a2dd95SBruce Richardson 	const struct rte_memzone *mz;
14799a2dd95SBruce Richardson 	char mz_name[DATA_MZ_NAME_MAX_LEN];
14899a2dd95SBruce Richardson 	int n, ret;
14999a2dd95SBruce Richardson 	struct rte_eventdev *dev;
15099a2dd95SBruce Richardson 
151f3f3a917SPavan Nikhilesh 	if (adapters == NULL) {
152f3f3a917SPavan Nikhilesh 		adapters = rte_zmalloc("Eventdev",
153f3f3a917SPavan Nikhilesh 				       sizeof(struct rte_event_timer_adapter) *
154f3f3a917SPavan Nikhilesh 					       RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
155f3f3a917SPavan Nikhilesh 				       RTE_CACHE_LINE_SIZE);
156f3f3a917SPavan Nikhilesh 		if (adapters == NULL) {
157f3f3a917SPavan Nikhilesh 			rte_errno = ENOMEM;
158f3f3a917SPavan Nikhilesh 			return NULL;
159f3f3a917SPavan Nikhilesh 		}
160f3f3a917SPavan Nikhilesh 	}
161f3f3a917SPavan Nikhilesh 
16299a2dd95SBruce Richardson 	if (conf == NULL) {
16399a2dd95SBruce Richardson 		rte_errno = EINVAL;
16499a2dd95SBruce Richardson 		return NULL;
16599a2dd95SBruce Richardson 	}
16699a2dd95SBruce Richardson 
16799a2dd95SBruce Richardson 	/* Check eventdev ID */
16899a2dd95SBruce Richardson 	if (!rte_event_pmd_is_valid_dev(conf->event_dev_id)) {
16999a2dd95SBruce Richardson 		rte_errno = EINVAL;
17099a2dd95SBruce Richardson 		return NULL;
17199a2dd95SBruce Richardson 	}
17299a2dd95SBruce Richardson 	dev = &rte_eventdevs[conf->event_dev_id];
17399a2dd95SBruce Richardson 
17499a2dd95SBruce Richardson 	adapter_id = conf->timer_adapter_id;
17599a2dd95SBruce Richardson 
17699a2dd95SBruce Richardson 	/* Check that adapter_id is in range */
17799a2dd95SBruce Richardson 	if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
17899a2dd95SBruce Richardson 		rte_errno = EINVAL;
17999a2dd95SBruce Richardson 		return NULL;
18099a2dd95SBruce Richardson 	}
18199a2dd95SBruce Richardson 
18299a2dd95SBruce Richardson 	/* Check adapter ID not already allocated */
18399a2dd95SBruce Richardson 	adapter = &adapters[adapter_id];
18499a2dd95SBruce Richardson 	if (adapter->allocated) {
18599a2dd95SBruce Richardson 		rte_errno = EEXIST;
18699a2dd95SBruce Richardson 		return NULL;
18799a2dd95SBruce Richardson 	}
18899a2dd95SBruce Richardson 
18999a2dd95SBruce Richardson 	/* Create shared data area. */
19099a2dd95SBruce Richardson 	n = snprintf(mz_name, sizeof(mz_name), DATA_MZ_NAME_FORMAT, adapter_id);
19199a2dd95SBruce Richardson 	if (n >= (int)sizeof(mz_name)) {
19299a2dd95SBruce Richardson 		rte_errno = EINVAL;
19399a2dd95SBruce Richardson 		return NULL;
19499a2dd95SBruce Richardson 	}
19599a2dd95SBruce Richardson 	mz = rte_memzone_reserve(mz_name,
19699a2dd95SBruce Richardson 				 sizeof(struct rte_event_timer_adapter_data),
19799a2dd95SBruce Richardson 				 conf->socket_id, 0);
19899a2dd95SBruce Richardson 	if (mz == NULL)
19999a2dd95SBruce Richardson 		/* rte_errno set by rte_memzone_reserve */
20099a2dd95SBruce Richardson 		return NULL;
20199a2dd95SBruce Richardson 
20299a2dd95SBruce Richardson 	adapter->data = mz->addr;
20399a2dd95SBruce Richardson 	memset(adapter->data, 0, sizeof(struct rte_event_timer_adapter_data));
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	adapter->data->mz = mz;
20699a2dd95SBruce Richardson 	adapter->data->event_dev_id = conf->event_dev_id;
20799a2dd95SBruce Richardson 	adapter->data->id = adapter_id;
20899a2dd95SBruce Richardson 	adapter->data->socket_id = conf->socket_id;
20999a2dd95SBruce Richardson 	adapter->data->conf = *conf;  /* copy conf structure */
21099a2dd95SBruce Richardson 
21199a2dd95SBruce Richardson 	/* Query eventdev PMD for timer adapter capabilities and ops */
2123d9d8adfSNaga Harish K S V 	if (dev->dev_ops->timer_adapter_caps_get) {
21399a2dd95SBruce Richardson 		ret = dev->dev_ops->timer_adapter_caps_get(dev,
21499a2dd95SBruce Richardson 				adapter->data->conf.flags,
2153d9d8adfSNaga Harish K S V 				&adapter->data->caps, &adapter->ops);
21699a2dd95SBruce Richardson 		if (ret < 0) {
21799a2dd95SBruce Richardson 			rte_errno = -ret;
21899a2dd95SBruce Richardson 			goto free_memzone;
21999a2dd95SBruce Richardson 		}
2203d9d8adfSNaga Harish K S V 	}
22199a2dd95SBruce Richardson 
22299a2dd95SBruce Richardson 	if (!(adapter->data->caps &
22399a2dd95SBruce Richardson 	      RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
22499a2dd95SBruce Richardson 		FUNC_PTR_OR_NULL_RET_WITH_ERRNO(conf_cb, EINVAL);
22599a2dd95SBruce Richardson 		ret = conf_cb(adapter->data->id, adapter->data->event_dev_id,
22699a2dd95SBruce Richardson 			      &adapter->data->event_port_id, conf_arg);
22799a2dd95SBruce Richardson 		if (ret < 0) {
22899a2dd95SBruce Richardson 			rte_errno = -ret;
22999a2dd95SBruce Richardson 			goto free_memzone;
23099a2dd95SBruce Richardson 		}
23199a2dd95SBruce Richardson 	}
23299a2dd95SBruce Richardson 
23399a2dd95SBruce Richardson 	/* If eventdev PMD did not provide ops, use default software
23499a2dd95SBruce Richardson 	 * implementation.
23599a2dd95SBruce Richardson 	 */
23699a2dd95SBruce Richardson 	if (adapter->ops == NULL)
23799a2dd95SBruce Richardson 		adapter->ops = &swtim_ops;
23899a2dd95SBruce Richardson 
23999a2dd95SBruce Richardson 	/* Allow driver to do some setup */
24099a2dd95SBruce Richardson 	FUNC_PTR_OR_NULL_RET_WITH_ERRNO(adapter->ops->init, ENOTSUP);
24199a2dd95SBruce Richardson 	ret = adapter->ops->init(adapter);
24299a2dd95SBruce Richardson 	if (ret < 0) {
24399a2dd95SBruce Richardson 		rte_errno = -ret;
24499a2dd95SBruce Richardson 		goto free_memzone;
24599a2dd95SBruce Richardson 	}
24699a2dd95SBruce Richardson 
24799a2dd95SBruce Richardson 	/* Set fast-path function pointers */
24899a2dd95SBruce Richardson 	adapter->arm_burst = adapter->ops->arm_burst;
24999a2dd95SBruce Richardson 	adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
25099a2dd95SBruce Richardson 	adapter->cancel_burst = adapter->ops->cancel_burst;
25199a2dd95SBruce Richardson 
25299a2dd95SBruce Richardson 	adapter->allocated = 1;
25399a2dd95SBruce Richardson 
25499a2dd95SBruce Richardson 	rte_eventdev_trace_timer_adapter_create(adapter_id, adapter, conf,
25599a2dd95SBruce Richardson 		conf_cb);
25699a2dd95SBruce Richardson 	return adapter;
25799a2dd95SBruce Richardson 
25899a2dd95SBruce Richardson free_memzone:
25999a2dd95SBruce Richardson 	rte_memzone_free(adapter->data->mz);
26099a2dd95SBruce Richardson 	return NULL;
26199a2dd95SBruce Richardson }
26299a2dd95SBruce Richardson 
26399a2dd95SBruce Richardson int
26499a2dd95SBruce Richardson rte_event_timer_adapter_get_info(const struct rte_event_timer_adapter *adapter,
26599a2dd95SBruce Richardson 		struct rte_event_timer_adapter_info *adapter_info)
26699a2dd95SBruce Richardson {
26799a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
26899a2dd95SBruce Richardson 
26999a2dd95SBruce Richardson 	if (adapter->ops->get_info)
27099a2dd95SBruce Richardson 		/* let driver set values it knows */
27199a2dd95SBruce Richardson 		adapter->ops->get_info(adapter, adapter_info);
27299a2dd95SBruce Richardson 
27399a2dd95SBruce Richardson 	/* Set common values */
27499a2dd95SBruce Richardson 	adapter_info->conf = adapter->data->conf;
27599a2dd95SBruce Richardson 	adapter_info->event_dev_port_id = adapter->data->event_port_id;
27699a2dd95SBruce Richardson 	adapter_info->caps = adapter->data->caps;
27799a2dd95SBruce Richardson 
27899a2dd95SBruce Richardson 	return 0;
27999a2dd95SBruce Richardson }
28099a2dd95SBruce Richardson 
28199a2dd95SBruce Richardson int
28299a2dd95SBruce Richardson rte_event_timer_adapter_start(const struct rte_event_timer_adapter *adapter)
28399a2dd95SBruce Richardson {
28499a2dd95SBruce Richardson 	int ret;
28599a2dd95SBruce Richardson 
28699a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
28799a2dd95SBruce Richardson 	FUNC_PTR_OR_ERR_RET(adapter->ops->start, -EINVAL);
28899a2dd95SBruce Richardson 
28999a2dd95SBruce Richardson 	if (adapter->data->started) {
29099a2dd95SBruce Richardson 		EVTIM_LOG_ERR("event timer adapter %"PRIu8" already started",
29199a2dd95SBruce Richardson 			      adapter->data->id);
29299a2dd95SBruce Richardson 		return -EALREADY;
29399a2dd95SBruce Richardson 	}
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson 	ret = adapter->ops->start(adapter);
29699a2dd95SBruce Richardson 	if (ret < 0)
29799a2dd95SBruce Richardson 		return ret;
29899a2dd95SBruce Richardson 
29999a2dd95SBruce Richardson 	adapter->data->started = 1;
30099a2dd95SBruce Richardson 	rte_eventdev_trace_timer_adapter_start(adapter);
30199a2dd95SBruce Richardson 	return 0;
30299a2dd95SBruce Richardson }
30399a2dd95SBruce Richardson 
30499a2dd95SBruce Richardson int
30599a2dd95SBruce Richardson rte_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter)
30699a2dd95SBruce Richardson {
30799a2dd95SBruce Richardson 	int ret;
30899a2dd95SBruce Richardson 
30999a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
31099a2dd95SBruce Richardson 	FUNC_PTR_OR_ERR_RET(adapter->ops->stop, -EINVAL);
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson 	if (adapter->data->started == 0) {
31399a2dd95SBruce Richardson 		EVTIM_LOG_ERR("event timer adapter %"PRIu8" already stopped",
31499a2dd95SBruce Richardson 			      adapter->data->id);
31599a2dd95SBruce Richardson 		return 0;
31699a2dd95SBruce Richardson 	}
31799a2dd95SBruce Richardson 
31899a2dd95SBruce Richardson 	ret = adapter->ops->stop(adapter);
31999a2dd95SBruce Richardson 	if (ret < 0)
32099a2dd95SBruce Richardson 		return ret;
32199a2dd95SBruce Richardson 
32299a2dd95SBruce Richardson 	adapter->data->started = 0;
32399a2dd95SBruce Richardson 	rte_eventdev_trace_timer_adapter_stop(adapter);
32499a2dd95SBruce Richardson 	return 0;
32599a2dd95SBruce Richardson }
32699a2dd95SBruce Richardson 
32799a2dd95SBruce Richardson struct rte_event_timer_adapter *
32899a2dd95SBruce Richardson rte_event_timer_adapter_lookup(uint16_t adapter_id)
32999a2dd95SBruce Richardson {
33099a2dd95SBruce Richardson 	char name[DATA_MZ_NAME_MAX_LEN];
33199a2dd95SBruce Richardson 	const struct rte_memzone *mz;
33299a2dd95SBruce Richardson 	struct rte_event_timer_adapter_data *data;
33399a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter;
33499a2dd95SBruce Richardson 	int ret;
33599a2dd95SBruce Richardson 	struct rte_eventdev *dev;
33699a2dd95SBruce Richardson 
337f3f3a917SPavan Nikhilesh 	if (adapters == NULL) {
338f3f3a917SPavan Nikhilesh 		adapters = rte_zmalloc("Eventdev",
339f3f3a917SPavan Nikhilesh 				       sizeof(struct rte_event_timer_adapter) *
340f3f3a917SPavan Nikhilesh 					       RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
341f3f3a917SPavan Nikhilesh 				       RTE_CACHE_LINE_SIZE);
342f3f3a917SPavan Nikhilesh 		if (adapters == NULL) {
343f3f3a917SPavan Nikhilesh 			rte_errno = ENOMEM;
344f3f3a917SPavan Nikhilesh 			return NULL;
345f3f3a917SPavan Nikhilesh 		}
346f3f3a917SPavan Nikhilesh 	}
347f3f3a917SPavan Nikhilesh 
34899a2dd95SBruce Richardson 	if (adapters[adapter_id].allocated)
34999a2dd95SBruce Richardson 		return &adapters[adapter_id]; /* Adapter is already loaded */
35099a2dd95SBruce Richardson 
35199a2dd95SBruce Richardson 	snprintf(name, DATA_MZ_NAME_MAX_LEN, DATA_MZ_NAME_FORMAT, adapter_id);
35299a2dd95SBruce Richardson 	mz = rte_memzone_lookup(name);
35399a2dd95SBruce Richardson 	if (mz == NULL) {
35499a2dd95SBruce Richardson 		rte_errno = ENOENT;
35599a2dd95SBruce Richardson 		return NULL;
35699a2dd95SBruce Richardson 	}
35799a2dd95SBruce Richardson 
35899a2dd95SBruce Richardson 	data = mz->addr;
35999a2dd95SBruce Richardson 
36099a2dd95SBruce Richardson 	adapter = &adapters[data->id];
36199a2dd95SBruce Richardson 	adapter->data = data;
36299a2dd95SBruce Richardson 
36399a2dd95SBruce Richardson 	dev = &rte_eventdevs[adapter->data->event_dev_id];
36499a2dd95SBruce Richardson 
36599a2dd95SBruce Richardson 	/* Query eventdev PMD for timer adapter capabilities and ops */
3663d9d8adfSNaga Harish K S V 	if (dev->dev_ops->timer_adapter_caps_get) {
36799a2dd95SBruce Richardson 		ret = dev->dev_ops->timer_adapter_caps_get(dev,
36899a2dd95SBruce Richardson 				adapter->data->conf.flags,
3693d9d8adfSNaga Harish K S V 				&adapter->data->caps, &adapter->ops);
37099a2dd95SBruce Richardson 		if (ret < 0) {
37199a2dd95SBruce Richardson 			rte_errno = EINVAL;
37299a2dd95SBruce Richardson 			return NULL;
37399a2dd95SBruce Richardson 		}
3743d9d8adfSNaga Harish K S V 	}
37599a2dd95SBruce Richardson 
37699a2dd95SBruce Richardson 	/* If eventdev PMD did not provide ops, use default software
37799a2dd95SBruce Richardson 	 * implementation.
37899a2dd95SBruce Richardson 	 */
37999a2dd95SBruce Richardson 	if (adapter->ops == NULL)
38099a2dd95SBruce Richardson 		adapter->ops = &swtim_ops;
38199a2dd95SBruce Richardson 
38299a2dd95SBruce Richardson 	/* Set fast-path function pointers */
38399a2dd95SBruce Richardson 	adapter->arm_burst = adapter->ops->arm_burst;
38499a2dd95SBruce Richardson 	adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
38599a2dd95SBruce Richardson 	adapter->cancel_burst = adapter->ops->cancel_burst;
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson 	adapter->allocated = 1;
38899a2dd95SBruce Richardson 
38999a2dd95SBruce Richardson 	return adapter;
39099a2dd95SBruce Richardson }
39199a2dd95SBruce Richardson 
39299a2dd95SBruce Richardson int
39399a2dd95SBruce Richardson rte_event_timer_adapter_free(struct rte_event_timer_adapter *adapter)
39499a2dd95SBruce Richardson {
395f3f3a917SPavan Nikhilesh 	int i, ret;
39699a2dd95SBruce Richardson 
39799a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
39899a2dd95SBruce Richardson 	FUNC_PTR_OR_ERR_RET(adapter->ops->uninit, -EINVAL);
39999a2dd95SBruce Richardson 
40099a2dd95SBruce Richardson 	if (adapter->data->started == 1) {
40199a2dd95SBruce Richardson 		EVTIM_LOG_ERR("event timer adapter %"PRIu8" must be stopped "
40299a2dd95SBruce Richardson 			      "before freeing", adapter->data->id);
40399a2dd95SBruce Richardson 		return -EBUSY;
40499a2dd95SBruce Richardson 	}
40599a2dd95SBruce Richardson 
40699a2dd95SBruce Richardson 	/* free impl priv data */
40799a2dd95SBruce Richardson 	ret = adapter->ops->uninit(adapter);
40899a2dd95SBruce Richardson 	if (ret < 0)
40999a2dd95SBruce Richardson 		return ret;
41099a2dd95SBruce Richardson 
41199a2dd95SBruce Richardson 	/* free shared data area */
41299a2dd95SBruce Richardson 	ret = rte_memzone_free(adapter->data->mz);
41399a2dd95SBruce Richardson 	if (ret < 0)
41499a2dd95SBruce Richardson 		return ret;
41599a2dd95SBruce Richardson 
41699a2dd95SBruce Richardson 	adapter->data = NULL;
41799a2dd95SBruce Richardson 	adapter->allocated = 0;
41899a2dd95SBruce Richardson 
419f3f3a917SPavan Nikhilesh 	ret = 0;
420f3f3a917SPavan Nikhilesh 	for (i = 0; i < RTE_EVENT_TIMER_ADAPTER_NUM_MAX; i++)
421f3f3a917SPavan Nikhilesh 		if (adapters[i].allocated)
422f3f3a917SPavan Nikhilesh 			ret = adapters[i].allocated;
423f3f3a917SPavan Nikhilesh 
424f3f3a917SPavan Nikhilesh 	if (!ret) {
425f3f3a917SPavan Nikhilesh 		rte_free(adapters);
426f3f3a917SPavan Nikhilesh 		adapters = NULL;
427f3f3a917SPavan Nikhilesh 	}
428f3f3a917SPavan Nikhilesh 
42999a2dd95SBruce Richardson 	rte_eventdev_trace_timer_adapter_free(adapter);
43099a2dd95SBruce Richardson 	return 0;
43199a2dd95SBruce Richardson }
43299a2dd95SBruce Richardson 
43399a2dd95SBruce Richardson int
43499a2dd95SBruce Richardson rte_event_timer_adapter_service_id_get(struct rte_event_timer_adapter *adapter,
43599a2dd95SBruce Richardson 				       uint32_t *service_id)
43699a2dd95SBruce Richardson {
43799a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
43899a2dd95SBruce Richardson 
43999a2dd95SBruce Richardson 	if (adapter->data->service_inited && service_id != NULL)
44099a2dd95SBruce Richardson 		*service_id = adapter->data->service_id;
44199a2dd95SBruce Richardson 
44299a2dd95SBruce Richardson 	return adapter->data->service_inited ? 0 : -ESRCH;
44399a2dd95SBruce Richardson }
44499a2dd95SBruce Richardson 
44599a2dd95SBruce Richardson int
44699a2dd95SBruce Richardson rte_event_timer_adapter_stats_get(struct rte_event_timer_adapter *adapter,
44799a2dd95SBruce Richardson 				  struct rte_event_timer_adapter_stats *stats)
44899a2dd95SBruce Richardson {
44999a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
45099a2dd95SBruce Richardson 	FUNC_PTR_OR_ERR_RET(adapter->ops->stats_get, -EINVAL);
45199a2dd95SBruce Richardson 	if (stats == NULL)
45299a2dd95SBruce Richardson 		return -EINVAL;
45399a2dd95SBruce Richardson 
45499a2dd95SBruce Richardson 	return adapter->ops->stats_get(adapter, stats);
45599a2dd95SBruce Richardson }
45699a2dd95SBruce Richardson 
45799a2dd95SBruce Richardson int
45899a2dd95SBruce Richardson rte_event_timer_adapter_stats_reset(struct rte_event_timer_adapter *adapter)
45999a2dd95SBruce Richardson {
46099a2dd95SBruce Richardson 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
46199a2dd95SBruce Richardson 	FUNC_PTR_OR_ERR_RET(adapter->ops->stats_reset, -EINVAL);
46299a2dd95SBruce Richardson 	return adapter->ops->stats_reset(adapter);
46399a2dd95SBruce Richardson }
46499a2dd95SBruce Richardson 
4650727ff34SErik Gabriel Carrillo int
4660727ff34SErik Gabriel Carrillo rte_event_timer_remaining_ticks_get(
4670727ff34SErik Gabriel Carrillo 			const struct rte_event_timer_adapter *adapter,
4680727ff34SErik Gabriel Carrillo 			const struct rte_event_timer *evtim,
4690727ff34SErik Gabriel Carrillo 			uint64_t *ticks_remaining)
4700727ff34SErik Gabriel Carrillo {
4710727ff34SErik Gabriel Carrillo 	ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
4720727ff34SErik Gabriel Carrillo 	FUNC_PTR_OR_ERR_RET(adapter->ops->remaining_ticks_get, -ENOTSUP);
4730727ff34SErik Gabriel Carrillo 
4740727ff34SErik Gabriel Carrillo 	if (ticks_remaining == NULL)
4750727ff34SErik Gabriel Carrillo 		return -EINVAL;
4760727ff34SErik Gabriel Carrillo 
4770727ff34SErik Gabriel Carrillo 	return adapter->ops->remaining_ticks_get(adapter, evtim,
4780727ff34SErik Gabriel Carrillo 						 ticks_remaining);
4790727ff34SErik Gabriel Carrillo }
4800727ff34SErik Gabriel Carrillo 
48199a2dd95SBruce Richardson /*
48299a2dd95SBruce Richardson  * Software event timer adapter buffer helper functions
48399a2dd95SBruce Richardson  */
48499a2dd95SBruce Richardson 
48599a2dd95SBruce Richardson #define NSECPERSEC 1E9
48699a2dd95SBruce Richardson 
48799a2dd95SBruce Richardson /* Optimizations used to index into the buffer require that the buffer size
48899a2dd95SBruce Richardson  * be a power of 2.
48999a2dd95SBruce Richardson  */
49099a2dd95SBruce Richardson #define EVENT_BUFFER_SZ 4096
49199a2dd95SBruce Richardson #define EVENT_BUFFER_BATCHSZ 32
49299a2dd95SBruce Richardson #define EVENT_BUFFER_MASK (EVENT_BUFFER_SZ - 1)
49399a2dd95SBruce Richardson 
49499a2dd95SBruce Richardson #define EXP_TIM_BUF_SZ 128
49599a2dd95SBruce Richardson 
49699a2dd95SBruce Richardson struct event_buffer {
49799a2dd95SBruce Richardson 	size_t head;
49899a2dd95SBruce Richardson 	size_t tail;
49999a2dd95SBruce Richardson 	struct rte_event events[EVENT_BUFFER_SZ];
50099a2dd95SBruce Richardson } __rte_cache_aligned;
50199a2dd95SBruce Richardson 
50299a2dd95SBruce Richardson static inline bool
50399a2dd95SBruce Richardson event_buffer_full(struct event_buffer *bufp)
50499a2dd95SBruce Richardson {
50599a2dd95SBruce Richardson 	return (bufp->head - bufp->tail) == EVENT_BUFFER_SZ;
50699a2dd95SBruce Richardson }
50799a2dd95SBruce Richardson 
50899a2dd95SBruce Richardson static inline bool
50999a2dd95SBruce Richardson event_buffer_batch_ready(struct event_buffer *bufp)
51099a2dd95SBruce Richardson {
51199a2dd95SBruce Richardson 	return (bufp->head - bufp->tail) >= EVENT_BUFFER_BATCHSZ;
51299a2dd95SBruce Richardson }
51399a2dd95SBruce Richardson 
51499a2dd95SBruce Richardson static void
51599a2dd95SBruce Richardson event_buffer_init(struct event_buffer *bufp)
51699a2dd95SBruce Richardson {
51799a2dd95SBruce Richardson 	bufp->head = bufp->tail = 0;
51899a2dd95SBruce Richardson 	memset(&bufp->events, 0, sizeof(struct rte_event) * EVENT_BUFFER_SZ);
51999a2dd95SBruce Richardson }
52099a2dd95SBruce Richardson 
52199a2dd95SBruce Richardson static int
52299a2dd95SBruce Richardson event_buffer_add(struct event_buffer *bufp, struct rte_event *eventp)
52399a2dd95SBruce Richardson {
52499a2dd95SBruce Richardson 	size_t head_idx;
52599a2dd95SBruce Richardson 	struct rte_event *buf_eventp;
52699a2dd95SBruce Richardson 
52799a2dd95SBruce Richardson 	if (event_buffer_full(bufp))
52899a2dd95SBruce Richardson 		return -1;
52999a2dd95SBruce Richardson 
53099a2dd95SBruce Richardson 	/* Instead of modulus, bitwise AND with mask to get head_idx. */
53199a2dd95SBruce Richardson 	head_idx = bufp->head & EVENT_BUFFER_MASK;
53299a2dd95SBruce Richardson 	buf_eventp = &bufp->events[head_idx];
53399a2dd95SBruce Richardson 	rte_memcpy(buf_eventp, eventp, sizeof(struct rte_event));
53499a2dd95SBruce Richardson 
53599a2dd95SBruce Richardson 	/* Wrap automatically when overflow occurs. */
53699a2dd95SBruce Richardson 	bufp->head++;
53799a2dd95SBruce Richardson 
53899a2dd95SBruce Richardson 	return 0;
53999a2dd95SBruce Richardson }
54099a2dd95SBruce Richardson 
54199a2dd95SBruce Richardson static void
54299a2dd95SBruce Richardson event_buffer_flush(struct event_buffer *bufp, uint8_t dev_id, uint8_t port_id,
54399a2dd95SBruce Richardson 		   uint16_t *nb_events_flushed,
54499a2dd95SBruce Richardson 		   uint16_t *nb_events_inv)
54599a2dd95SBruce Richardson {
54699a2dd95SBruce Richardson 	struct rte_event *events = bufp->events;
54799a2dd95SBruce Richardson 	size_t head_idx, tail_idx;
54899a2dd95SBruce Richardson 	uint16_t n = 0;
54999a2dd95SBruce Richardson 
55099a2dd95SBruce Richardson 	/* Instead of modulus, bitwise AND with mask to get index. */
55199a2dd95SBruce Richardson 	head_idx = bufp->head & EVENT_BUFFER_MASK;
55299a2dd95SBruce Richardson 	tail_idx = bufp->tail & EVENT_BUFFER_MASK;
55399a2dd95SBruce Richardson 
55499a2dd95SBruce Richardson 	RTE_ASSERT(head_idx < EVENT_BUFFER_SZ && tail_idx < EVENT_BUFFER_SZ);
55599a2dd95SBruce Richardson 
5564a6672c2SStephen Hemminger 	/* Determine the largest contiguous run we can attempt to enqueue to the
55799a2dd95SBruce Richardson 	 * event device.
55899a2dd95SBruce Richardson 	 */
55999a2dd95SBruce Richardson 	if (head_idx > tail_idx)
56099a2dd95SBruce Richardson 		n = head_idx - tail_idx;
56199a2dd95SBruce Richardson 	else if (head_idx < tail_idx)
56299a2dd95SBruce Richardson 		n = EVENT_BUFFER_SZ - tail_idx;
56399a2dd95SBruce Richardson 	else if (event_buffer_full(bufp))
56499a2dd95SBruce Richardson 		n = EVENT_BUFFER_SZ - tail_idx;
56599a2dd95SBruce Richardson 	else {
56699a2dd95SBruce Richardson 		*nb_events_flushed = 0;
56799a2dd95SBruce Richardson 		return;
56899a2dd95SBruce Richardson 	}
56999a2dd95SBruce Richardson 
57099a2dd95SBruce Richardson 	n = RTE_MIN(EVENT_BUFFER_BATCHSZ, n);
57199a2dd95SBruce Richardson 	*nb_events_inv = 0;
57299a2dd95SBruce Richardson 
57399a2dd95SBruce Richardson 	*nb_events_flushed = rte_event_enqueue_burst(dev_id, port_id,
57499a2dd95SBruce Richardson 						     &events[tail_idx], n);
57599a2dd95SBruce Richardson 	if (*nb_events_flushed != n) {
57699a2dd95SBruce Richardson 		if (rte_errno == EINVAL) {
57799a2dd95SBruce Richardson 			EVTIM_LOG_ERR("failed to enqueue invalid event - "
57899a2dd95SBruce Richardson 				      "dropping it");
57999a2dd95SBruce Richardson 			(*nb_events_inv)++;
58099a2dd95SBruce Richardson 		} else if (rte_errno == ENOSPC)
58199a2dd95SBruce Richardson 			rte_pause();
58299a2dd95SBruce Richardson 	}
58399a2dd95SBruce Richardson 
58499a2dd95SBruce Richardson 	if (*nb_events_flushed > 0)
58599a2dd95SBruce Richardson 		EVTIM_BUF_LOG_DBG("enqueued %"PRIu16" timer events to event "
58699a2dd95SBruce Richardson 				  "device", *nb_events_flushed);
58799a2dd95SBruce Richardson 
58899a2dd95SBruce Richardson 	bufp->tail = bufp->tail + *nb_events_flushed + *nb_events_inv;
58999a2dd95SBruce Richardson }
59099a2dd95SBruce Richardson 
59199a2dd95SBruce Richardson /*
59299a2dd95SBruce Richardson  * Software event timer adapter implementation
59399a2dd95SBruce Richardson  */
59499a2dd95SBruce Richardson struct swtim {
59599a2dd95SBruce Richardson 	/* Identifier of service executing timer management logic. */
59699a2dd95SBruce Richardson 	uint32_t service_id;
59799a2dd95SBruce Richardson 	/* The cycle count at which the adapter should next tick */
59899a2dd95SBruce Richardson 	uint64_t next_tick_cycles;
59999a2dd95SBruce Richardson 	/* The tick resolution used by adapter instance. May have been
60099a2dd95SBruce Richardson 	 * adjusted from what user requested
60199a2dd95SBruce Richardson 	 */
60299a2dd95SBruce Richardson 	uint64_t timer_tick_ns;
60399a2dd95SBruce Richardson 	/* Maximum timeout in nanoseconds allowed by adapter instance. */
60499a2dd95SBruce Richardson 	uint64_t max_tmo_ns;
60599a2dd95SBruce Richardson 	/* Buffered timer expiry events to be enqueued to an event device. */
60699a2dd95SBruce Richardson 	struct event_buffer buffer;
60799a2dd95SBruce Richardson 	/* Statistics */
60899a2dd95SBruce Richardson 	struct rte_event_timer_adapter_stats stats;
60999a2dd95SBruce Richardson 	/* Mempool of timer objects */
61099a2dd95SBruce Richardson 	struct rte_mempool *tim_pool;
61199a2dd95SBruce Richardson 	/* Back pointer for convenience */
61299a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter;
61399a2dd95SBruce Richardson 	/* Identifier of timer data instance */
61499a2dd95SBruce Richardson 	uint32_t timer_data_id;
61599a2dd95SBruce Richardson 	/* Track which cores have actually armed a timer */
61699a2dd95SBruce Richardson 	struct {
61799a2dd95SBruce Richardson 		uint16_t v;
61899a2dd95SBruce Richardson 	} __rte_cache_aligned in_use[RTE_MAX_LCORE];
61999a2dd95SBruce Richardson 	/* Track which cores' timer lists should be polled */
62099a2dd95SBruce Richardson 	unsigned int poll_lcores[RTE_MAX_LCORE];
62199a2dd95SBruce Richardson 	/* The number of lists that should be polled */
62299a2dd95SBruce Richardson 	int n_poll_lcores;
62399a2dd95SBruce Richardson 	/* Timers which have expired and can be returned to a mempool */
62499a2dd95SBruce Richardson 	struct rte_timer *expired_timers[EXP_TIM_BUF_SZ];
62599a2dd95SBruce Richardson 	/* The number of timers that can be returned to a mempool */
62699a2dd95SBruce Richardson 	size_t n_expired_timers;
62799a2dd95SBruce Richardson };
62899a2dd95SBruce Richardson 
62999a2dd95SBruce Richardson static inline struct swtim *
63099a2dd95SBruce Richardson swtim_pmd_priv(const struct rte_event_timer_adapter *adapter)
63199a2dd95SBruce Richardson {
63299a2dd95SBruce Richardson 	return adapter->data->adapter_priv;
63399a2dd95SBruce Richardson }
63499a2dd95SBruce Richardson 
63599a2dd95SBruce Richardson static void
63699a2dd95SBruce Richardson swtim_callback(struct rte_timer *tim)
63799a2dd95SBruce Richardson {
63899a2dd95SBruce Richardson 	struct rte_event_timer *evtim = tim->arg;
63999a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter;
64099a2dd95SBruce Richardson 	unsigned int lcore = rte_lcore_id();
64199a2dd95SBruce Richardson 	struct swtim *sw;
64299a2dd95SBruce Richardson 	uint16_t nb_evs_flushed = 0;
64399a2dd95SBruce Richardson 	uint16_t nb_evs_invalid = 0;
64499a2dd95SBruce Richardson 	uint64_t opaque;
64599a2dd95SBruce Richardson 	int ret;
64699a2dd95SBruce Richardson 	int n_lcores;
6473d9d8adfSNaga Harish K S V 	enum rte_timer_type type;
64899a2dd95SBruce Richardson 
64999a2dd95SBruce Richardson 	opaque = evtim->impl_opaque[1];
65099a2dd95SBruce Richardson 	adapter = (struct rte_event_timer_adapter *)(uintptr_t)opaque;
65199a2dd95SBruce Richardson 	sw = swtim_pmd_priv(adapter);
6523d9d8adfSNaga Harish K S V 	type = get_timer_type(adapter);
65399a2dd95SBruce Richardson 
65499a2dd95SBruce Richardson 	if (unlikely(sw->in_use[lcore].v == 0)) {
65599a2dd95SBruce Richardson 		sw->in_use[lcore].v = 1;
65699a2dd95SBruce Richardson 		n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
65799a2dd95SBruce Richardson 					     __ATOMIC_RELAXED);
65899a2dd95SBruce Richardson 		__atomic_store_n(&sw->poll_lcores[n_lcores], lcore,
65999a2dd95SBruce Richardson 				__ATOMIC_RELAXED);
66099a2dd95SBruce Richardson 	}
6613d9d8adfSNaga Harish K S V 
6623d9d8adfSNaga Harish K S V 	ret = event_buffer_add(&sw->buffer, &evtim->ev);
6633d9d8adfSNaga Harish K S V 	if (ret < 0) {
6643d9d8adfSNaga Harish K S V 		if (type == SINGLE) {
6653d9d8adfSNaga Harish K S V 			/* If event buffer is full, put timer back in list with
6663d9d8adfSNaga Harish K S V 			 * immediate expiry value, so that we process it again
6673d9d8adfSNaga Harish K S V 			 * on the next iteration.
6683d9d8adfSNaga Harish K S V 			 */
6693d9d8adfSNaga Harish K S V 			ret = rte_timer_alt_reset(sw->timer_data_id, tim, 0,
6703d9d8adfSNaga Harish K S V 						SINGLE,	lcore, NULL, evtim);
6713d9d8adfSNaga Harish K S V 			if (ret < 0) {
6723d9d8adfSNaga Harish K S V 				EVTIM_LOG_DBG("event buffer full, failed to "
6733d9d8adfSNaga Harish K S V 						"reset timer with immediate "
6743d9d8adfSNaga Harish K S V 						"expiry value");
6753d9d8adfSNaga Harish K S V 			} else {
6763d9d8adfSNaga Harish K S V 				sw->stats.evtim_retry_count++;
6773d9d8adfSNaga Harish K S V 				EVTIM_LOG_DBG("event buffer full, resetting "
6783d9d8adfSNaga Harish K S V 						"rte_timer with immediate "
6793d9d8adfSNaga Harish K S V 						"expiry value");
6803d9d8adfSNaga Harish K S V 			}
6813d9d8adfSNaga Harish K S V 		} else {
6823d9d8adfSNaga Harish K S V 			sw->stats.evtim_drop_count++;
6833d9d8adfSNaga Harish K S V 		}
6843d9d8adfSNaga Harish K S V 
68599a2dd95SBruce Richardson 	} else {
68699a2dd95SBruce Richardson 		EVTIM_BUF_LOG_DBG("buffered an event timer expiry event");
68799a2dd95SBruce Richardson 
68899a2dd95SBruce Richardson 		/* Empty the buffer here, if necessary, to free older expired
68999a2dd95SBruce Richardson 		 * timers only
69099a2dd95SBruce Richardson 		 */
69199a2dd95SBruce Richardson 		if (unlikely(sw->n_expired_timers == EXP_TIM_BUF_SZ)) {
69299a2dd95SBruce Richardson 			rte_mempool_put_bulk(sw->tim_pool,
69399a2dd95SBruce Richardson 					     (void **)sw->expired_timers,
69499a2dd95SBruce Richardson 					     sw->n_expired_timers);
69599a2dd95SBruce Richardson 			sw->n_expired_timers = 0;
69699a2dd95SBruce Richardson 		}
69799a2dd95SBruce Richardson 
6983d9d8adfSNaga Harish K S V 		/* Don't free rte_timer for a periodic event timer until
6993d9d8adfSNaga Harish K S V 		 * it is cancelled
7003d9d8adfSNaga Harish K S V 		 */
7013d9d8adfSNaga Harish K S V 		if (type == SINGLE)
70299a2dd95SBruce Richardson 			sw->expired_timers[sw->n_expired_timers++] = tim;
70399a2dd95SBruce Richardson 		sw->stats.evtim_exp_count++;
70499a2dd95SBruce Richardson 
7053d9d8adfSNaga Harish K S V 		if (type == SINGLE)
70699a2dd95SBruce Richardson 			__atomic_store_n(&evtim->state, RTE_EVENT_TIMER_NOT_ARMED,
70799a2dd95SBruce Richardson 				__ATOMIC_RELEASE);
70899a2dd95SBruce Richardson 	}
70999a2dd95SBruce Richardson 
71099a2dd95SBruce Richardson 	if (event_buffer_batch_ready(&sw->buffer)) {
71199a2dd95SBruce Richardson 		event_buffer_flush(&sw->buffer,
71299a2dd95SBruce Richardson 				   adapter->data->event_dev_id,
71399a2dd95SBruce Richardson 				   adapter->data->event_port_id,
71499a2dd95SBruce Richardson 				   &nb_evs_flushed,
71599a2dd95SBruce Richardson 				   &nb_evs_invalid);
71699a2dd95SBruce Richardson 
71799a2dd95SBruce Richardson 		sw->stats.ev_enq_count += nb_evs_flushed;
71899a2dd95SBruce Richardson 		sw->stats.ev_inv_count += nb_evs_invalid;
71999a2dd95SBruce Richardson 	}
72099a2dd95SBruce Richardson }
72199a2dd95SBruce Richardson 
72299a2dd95SBruce Richardson static __rte_always_inline uint64_t
72399a2dd95SBruce Richardson get_timeout_cycles(struct rte_event_timer *evtim,
72499a2dd95SBruce Richardson 		   const struct rte_event_timer_adapter *adapter)
72599a2dd95SBruce Richardson {
72699a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
72799a2dd95SBruce Richardson 	uint64_t timeout_ns = evtim->timeout_ticks * sw->timer_tick_ns;
72899a2dd95SBruce Richardson 	return timeout_ns * rte_get_timer_hz() / NSECPERSEC;
72999a2dd95SBruce Richardson }
73099a2dd95SBruce Richardson 
73199a2dd95SBruce Richardson /* This function returns true if one or more (adapter) ticks have occurred since
73299a2dd95SBruce Richardson  * the last time it was called.
73399a2dd95SBruce Richardson  */
73499a2dd95SBruce Richardson static inline bool
73599a2dd95SBruce Richardson swtim_did_tick(struct swtim *sw)
73699a2dd95SBruce Richardson {
73799a2dd95SBruce Richardson 	uint64_t cycles_per_adapter_tick, start_cycles;
73899a2dd95SBruce Richardson 	uint64_t *next_tick_cyclesp;
73999a2dd95SBruce Richardson 
74099a2dd95SBruce Richardson 	next_tick_cyclesp = &sw->next_tick_cycles;
74199a2dd95SBruce Richardson 	cycles_per_adapter_tick = sw->timer_tick_ns *
74299a2dd95SBruce Richardson 			(rte_get_timer_hz() / NSECPERSEC);
74399a2dd95SBruce Richardson 	start_cycles = rte_get_timer_cycles();
74499a2dd95SBruce Richardson 
74599a2dd95SBruce Richardson 	/* Note: initially, *next_tick_cyclesp == 0, so the clause below will
74699a2dd95SBruce Richardson 	 * execute, and set things going.
74799a2dd95SBruce Richardson 	 */
74899a2dd95SBruce Richardson 
74999a2dd95SBruce Richardson 	if (start_cycles >= *next_tick_cyclesp) {
75099a2dd95SBruce Richardson 		/* Snap the current cycle count to the preceding adapter tick
75199a2dd95SBruce Richardson 		 * boundary.
75299a2dd95SBruce Richardson 		 */
75399a2dd95SBruce Richardson 		start_cycles -= start_cycles % cycles_per_adapter_tick;
75499a2dd95SBruce Richardson 		*next_tick_cyclesp = start_cycles + cycles_per_adapter_tick;
75599a2dd95SBruce Richardson 
75699a2dd95SBruce Richardson 		return true;
75799a2dd95SBruce Richardson 	}
75899a2dd95SBruce Richardson 
75999a2dd95SBruce Richardson 	return false;
76099a2dd95SBruce Richardson }
76199a2dd95SBruce Richardson 
76299a2dd95SBruce Richardson /* Check that event timer timeout value is in range */
76399a2dd95SBruce Richardson static __rte_always_inline int
76499a2dd95SBruce Richardson check_timeout(struct rte_event_timer *evtim,
76599a2dd95SBruce Richardson 	      const struct rte_event_timer_adapter *adapter)
76699a2dd95SBruce Richardson {
76799a2dd95SBruce Richardson 	uint64_t tmo_nsec;
76899a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
76999a2dd95SBruce Richardson 
77099a2dd95SBruce Richardson 	tmo_nsec = evtim->timeout_ticks * sw->timer_tick_ns;
77199a2dd95SBruce Richardson 	if (tmo_nsec > sw->max_tmo_ns)
77299a2dd95SBruce Richardson 		return -1;
77399a2dd95SBruce Richardson 	if (tmo_nsec < sw->timer_tick_ns)
77499a2dd95SBruce Richardson 		return -2;
77599a2dd95SBruce Richardson 
77699a2dd95SBruce Richardson 	return 0;
77799a2dd95SBruce Richardson }
77899a2dd95SBruce Richardson 
77999a2dd95SBruce Richardson /* Check that event timer event queue sched type matches destination event queue
78099a2dd95SBruce Richardson  * sched type
78199a2dd95SBruce Richardson  */
78299a2dd95SBruce Richardson static __rte_always_inline int
78399a2dd95SBruce Richardson check_destination_event_queue(struct rte_event_timer *evtim,
78499a2dd95SBruce Richardson 			      const struct rte_event_timer_adapter *adapter)
78599a2dd95SBruce Richardson {
78699a2dd95SBruce Richardson 	int ret;
78799a2dd95SBruce Richardson 	uint32_t sched_type;
78899a2dd95SBruce Richardson 
78999a2dd95SBruce Richardson 	ret = rte_event_queue_attr_get(adapter->data->event_dev_id,
79099a2dd95SBruce Richardson 				       evtim->ev.queue_id,
79199a2dd95SBruce Richardson 				       RTE_EVENT_QUEUE_ATTR_SCHEDULE_TYPE,
79299a2dd95SBruce Richardson 				       &sched_type);
79399a2dd95SBruce Richardson 
79499a2dd95SBruce Richardson 	if ((ret == 0 && evtim->ev.sched_type == sched_type) ||
79599a2dd95SBruce Richardson 	    ret == -EOVERFLOW)
79699a2dd95SBruce Richardson 		return 0;
79799a2dd95SBruce Richardson 
79899a2dd95SBruce Richardson 	return -1;
79999a2dd95SBruce Richardson }
80099a2dd95SBruce Richardson 
80199a2dd95SBruce Richardson static int
80299a2dd95SBruce Richardson swtim_service_func(void *arg)
80399a2dd95SBruce Richardson {
80499a2dd95SBruce Richardson 	struct rte_event_timer_adapter *adapter = arg;
80599a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
80699a2dd95SBruce Richardson 	uint16_t nb_evs_flushed = 0;
80799a2dd95SBruce Richardson 	uint16_t nb_evs_invalid = 0;
808ed88c5a5SMattias Rönnblom 	const uint64_t prior_enq_count = sw->stats.ev_enq_count;
80999a2dd95SBruce Richardson 
81099a2dd95SBruce Richardson 	if (swtim_did_tick(sw)) {
81199a2dd95SBruce Richardson 		rte_timer_alt_manage(sw->timer_data_id,
81299a2dd95SBruce Richardson 				     sw->poll_lcores,
81399a2dd95SBruce Richardson 				     sw->n_poll_lcores,
81499a2dd95SBruce Richardson 				     swtim_callback);
81599a2dd95SBruce Richardson 
81699a2dd95SBruce Richardson 		/* Return expired timer objects back to mempool */
81799a2dd95SBruce Richardson 		rte_mempool_put_bulk(sw->tim_pool, (void **)sw->expired_timers,
81899a2dd95SBruce Richardson 				     sw->n_expired_timers);
81999a2dd95SBruce Richardson 		sw->n_expired_timers = 0;
82099a2dd95SBruce Richardson 
82199a2dd95SBruce Richardson 		event_buffer_flush(&sw->buffer,
82299a2dd95SBruce Richardson 				   adapter->data->event_dev_id,
82399a2dd95SBruce Richardson 				   adapter->data->event_port_id,
82499a2dd95SBruce Richardson 				   &nb_evs_flushed,
82599a2dd95SBruce Richardson 				   &nb_evs_invalid);
82699a2dd95SBruce Richardson 
82799a2dd95SBruce Richardson 		sw->stats.ev_enq_count += nb_evs_flushed;
82899a2dd95SBruce Richardson 		sw->stats.ev_inv_count += nb_evs_invalid;
82999a2dd95SBruce Richardson 		sw->stats.adapter_tick_count++;
83099a2dd95SBruce Richardson 	}
83199a2dd95SBruce Richardson 
832578402f2SMattias Rönnblom 	rte_event_maintain(adapter->data->event_dev_id,
833578402f2SMattias Rönnblom 			   adapter->data->event_port_id, 0);
834578402f2SMattias Rönnblom 
835ed88c5a5SMattias Rönnblom 	return prior_enq_count == sw->stats.ev_enq_count ? -EAGAIN : 0;
83699a2dd95SBruce Richardson }
83799a2dd95SBruce Richardson 
83899a2dd95SBruce Richardson /* The adapter initialization function rounds the mempool size up to the next
83999a2dd95SBruce Richardson  * power of 2, so we can take the difference between that value and what the
84099a2dd95SBruce Richardson  * user requested, and use the space for caches.  This avoids a scenario where a
84199a2dd95SBruce Richardson  * user can't arm the number of timers the adapter was configured with because
84299a2dd95SBruce Richardson  * mempool objects have been lost to caches.
84399a2dd95SBruce Richardson  *
84499a2dd95SBruce Richardson  * nb_actual should always be a power of 2, so we can iterate over the powers
84599a2dd95SBruce Richardson  * of 2 to see what the largest cache size we can use is.
84699a2dd95SBruce Richardson  */
84799a2dd95SBruce Richardson static int
84899a2dd95SBruce Richardson compute_msg_mempool_cache_size(uint64_t nb_requested, uint64_t nb_actual)
84999a2dd95SBruce Richardson {
85099a2dd95SBruce Richardson 	int i;
85199a2dd95SBruce Richardson 	int size;
85299a2dd95SBruce Richardson 	int cache_size = 0;
85399a2dd95SBruce Richardson 
85499a2dd95SBruce Richardson 	for (i = 0;; i++) {
85599a2dd95SBruce Richardson 		size = 1 << i;
85699a2dd95SBruce Richardson 
85799a2dd95SBruce Richardson 		if (RTE_MAX_LCORE * size < (int)(nb_actual - nb_requested) &&
85899a2dd95SBruce Richardson 		    size < RTE_MEMPOOL_CACHE_MAX_SIZE &&
85999a2dd95SBruce Richardson 		    size <= nb_actual / 1.5)
86099a2dd95SBruce Richardson 			cache_size = size;
86199a2dd95SBruce Richardson 		else
86299a2dd95SBruce Richardson 			break;
86399a2dd95SBruce Richardson 	}
86499a2dd95SBruce Richardson 
86599a2dd95SBruce Richardson 	return cache_size;
86699a2dd95SBruce Richardson }
86799a2dd95SBruce Richardson 
86899a2dd95SBruce Richardson static int
86999a2dd95SBruce Richardson swtim_init(struct rte_event_timer_adapter *adapter)
87099a2dd95SBruce Richardson {
87199a2dd95SBruce Richardson 	int i, ret;
87299a2dd95SBruce Richardson 	struct swtim *sw;
87399a2dd95SBruce Richardson 	unsigned int flags;
87499a2dd95SBruce Richardson 	struct rte_service_spec service;
87599a2dd95SBruce Richardson 
87699a2dd95SBruce Richardson 	/* Allocate storage for private data area */
87799a2dd95SBruce Richardson #define SWTIM_NAMESIZE 32
87899a2dd95SBruce Richardson 	char swtim_name[SWTIM_NAMESIZE];
87999a2dd95SBruce Richardson 	snprintf(swtim_name, SWTIM_NAMESIZE, "swtim_%"PRIu8,
88099a2dd95SBruce Richardson 			adapter->data->id);
88199a2dd95SBruce Richardson 	sw = rte_zmalloc_socket(swtim_name, sizeof(*sw), RTE_CACHE_LINE_SIZE,
88299a2dd95SBruce Richardson 			adapter->data->socket_id);
88399a2dd95SBruce Richardson 	if (sw == NULL) {
88499a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to allocate space for private data");
88599a2dd95SBruce Richardson 		rte_errno = ENOMEM;
88699a2dd95SBruce Richardson 		return -1;
88799a2dd95SBruce Richardson 	}
88899a2dd95SBruce Richardson 
88999a2dd95SBruce Richardson 	/* Connect storage to adapter instance */
89099a2dd95SBruce Richardson 	adapter->data->adapter_priv = sw;
89199a2dd95SBruce Richardson 	sw->adapter = adapter;
89299a2dd95SBruce Richardson 
89399a2dd95SBruce Richardson 	sw->timer_tick_ns = adapter->data->conf.timer_tick_ns;
89499a2dd95SBruce Richardson 	sw->max_tmo_ns = adapter->data->conf.max_tmo_ns;
89599a2dd95SBruce Richardson 
89699a2dd95SBruce Richardson 	/* Create a timer pool */
89799a2dd95SBruce Richardson 	char pool_name[SWTIM_NAMESIZE];
89899a2dd95SBruce Richardson 	snprintf(pool_name, SWTIM_NAMESIZE, "swtim_pool_%"PRIu8,
89999a2dd95SBruce Richardson 		 adapter->data->id);
90099a2dd95SBruce Richardson 	/* Optimal mempool size is a power of 2 minus one */
90199a2dd95SBruce Richardson 	uint64_t nb_timers = rte_align64pow2(adapter->data->conf.nb_timers);
90299a2dd95SBruce Richardson 	int pool_size = nb_timers - 1;
90399a2dd95SBruce Richardson 	int cache_size = compute_msg_mempool_cache_size(
90499a2dd95SBruce Richardson 				adapter->data->conf.nb_timers, nb_timers);
90599a2dd95SBruce Richardson 	flags = 0; /* pool is multi-producer, multi-consumer */
90699a2dd95SBruce Richardson 	sw->tim_pool = rte_mempool_create(pool_name, pool_size,
90799a2dd95SBruce Richardson 			sizeof(struct rte_timer), cache_size, 0, NULL, NULL,
90899a2dd95SBruce Richardson 			NULL, NULL, adapter->data->socket_id, flags);
90999a2dd95SBruce Richardson 	if (sw->tim_pool == NULL) {
91099a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to create timer object mempool");
91199a2dd95SBruce Richardson 		rte_errno = ENOMEM;
91299a2dd95SBruce Richardson 		goto free_alloc;
91399a2dd95SBruce Richardson 	}
91499a2dd95SBruce Richardson 
91599a2dd95SBruce Richardson 	/* Initialize the variables that track in-use timer lists */
91699a2dd95SBruce Richardson 	for (i = 0; i < RTE_MAX_LCORE; i++)
91799a2dd95SBruce Richardson 		sw->in_use[i].v = 0;
91899a2dd95SBruce Richardson 
91999a2dd95SBruce Richardson 	/* Initialize the timer subsystem and allocate timer data instance */
92099a2dd95SBruce Richardson 	ret = rte_timer_subsystem_init();
92199a2dd95SBruce Richardson 	if (ret < 0) {
92299a2dd95SBruce Richardson 		if (ret != -EALREADY) {
92399a2dd95SBruce Richardson 			EVTIM_LOG_ERR("failed to initialize timer subsystem");
92499a2dd95SBruce Richardson 			rte_errno = -ret;
92599a2dd95SBruce Richardson 			goto free_mempool;
92699a2dd95SBruce Richardson 		}
92799a2dd95SBruce Richardson 	}
92899a2dd95SBruce Richardson 
92999a2dd95SBruce Richardson 	ret = rte_timer_data_alloc(&sw->timer_data_id);
93099a2dd95SBruce Richardson 	if (ret < 0) {
93199a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to allocate timer data instance");
93299a2dd95SBruce Richardson 		rte_errno = -ret;
93399a2dd95SBruce Richardson 		goto free_mempool;
93499a2dd95SBruce Richardson 	}
93599a2dd95SBruce Richardson 
93699a2dd95SBruce Richardson 	/* Initialize timer event buffer */
93799a2dd95SBruce Richardson 	event_buffer_init(&sw->buffer);
93899a2dd95SBruce Richardson 
93999a2dd95SBruce Richardson 	sw->adapter = adapter;
94099a2dd95SBruce Richardson 
94199a2dd95SBruce Richardson 	/* Register a service component to run adapter logic */
94299a2dd95SBruce Richardson 	memset(&service, 0, sizeof(service));
94399a2dd95SBruce Richardson 	snprintf(service.name, RTE_SERVICE_NAME_MAX,
94499a2dd95SBruce Richardson 		 "swtim_svc_%"PRIu8, adapter->data->id);
94599a2dd95SBruce Richardson 	service.socket_id = adapter->data->socket_id;
94699a2dd95SBruce Richardson 	service.callback = swtim_service_func;
94799a2dd95SBruce Richardson 	service.callback_userdata = adapter;
94899a2dd95SBruce Richardson 	service.capabilities &= ~(RTE_SERVICE_CAP_MT_SAFE);
94999a2dd95SBruce Richardson 	ret = rte_service_component_register(&service, &sw->service_id);
95099a2dd95SBruce Richardson 	if (ret < 0) {
95199a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to register service %s with id %"PRIu32
95299a2dd95SBruce Richardson 			      ": err = %d", service.name, sw->service_id,
95399a2dd95SBruce Richardson 			      ret);
95499a2dd95SBruce Richardson 
95599a2dd95SBruce Richardson 		rte_errno = ENOSPC;
95699a2dd95SBruce Richardson 		goto free_mempool;
95799a2dd95SBruce Richardson 	}
95899a2dd95SBruce Richardson 
95999a2dd95SBruce Richardson 	EVTIM_LOG_DBG("registered service %s with id %"PRIu32, service.name,
96099a2dd95SBruce Richardson 		      sw->service_id);
96199a2dd95SBruce Richardson 
96299a2dd95SBruce Richardson 	adapter->data->service_id = sw->service_id;
96399a2dd95SBruce Richardson 	adapter->data->service_inited = 1;
96499a2dd95SBruce Richardson 
96599a2dd95SBruce Richardson 	return 0;
96699a2dd95SBruce Richardson free_mempool:
96799a2dd95SBruce Richardson 	rte_mempool_free(sw->tim_pool);
96899a2dd95SBruce Richardson free_alloc:
96999a2dd95SBruce Richardson 	rte_free(sw);
97099a2dd95SBruce Richardson 	return -1;
97199a2dd95SBruce Richardson }
97299a2dd95SBruce Richardson 
97399a2dd95SBruce Richardson static void
97499a2dd95SBruce Richardson swtim_free_tim(struct rte_timer *tim, void *arg)
97599a2dd95SBruce Richardson {
97699a2dd95SBruce Richardson 	struct swtim *sw = arg;
97799a2dd95SBruce Richardson 
97899a2dd95SBruce Richardson 	rte_mempool_put(sw->tim_pool, tim);
97999a2dd95SBruce Richardson }
98099a2dd95SBruce Richardson 
98199a2dd95SBruce Richardson /* Traverse the list of outstanding timers and put them back in the mempool
98299a2dd95SBruce Richardson  * before freeing the adapter to avoid leaking the memory.
98399a2dd95SBruce Richardson  */
98499a2dd95SBruce Richardson static int
98599a2dd95SBruce Richardson swtim_uninit(struct rte_event_timer_adapter *adapter)
98699a2dd95SBruce Richardson {
98799a2dd95SBruce Richardson 	int ret;
98899a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
98999a2dd95SBruce Richardson 
99099a2dd95SBruce Richardson 	/* Free outstanding timers */
99199a2dd95SBruce Richardson 	rte_timer_stop_all(sw->timer_data_id,
99299a2dd95SBruce Richardson 			   sw->poll_lcores,
99399a2dd95SBruce Richardson 			   sw->n_poll_lcores,
99499a2dd95SBruce Richardson 			   swtim_free_tim,
99599a2dd95SBruce Richardson 			   sw);
99699a2dd95SBruce Richardson 
9973d9d8adfSNaga Harish K S V 	ret = rte_timer_data_dealloc(sw->timer_data_id);
9983d9d8adfSNaga Harish K S V 	if (ret < 0) {
9993d9d8adfSNaga Harish K S V 		EVTIM_LOG_ERR("failed to deallocate timer data instance");
10003d9d8adfSNaga Harish K S V 		return ret;
10013d9d8adfSNaga Harish K S V 	}
10023d9d8adfSNaga Harish K S V 
100399a2dd95SBruce Richardson 	ret = rte_service_component_unregister(sw->service_id);
100499a2dd95SBruce Richardson 	if (ret < 0) {
100599a2dd95SBruce Richardson 		EVTIM_LOG_ERR("failed to unregister service component");
100699a2dd95SBruce Richardson 		return ret;
100799a2dd95SBruce Richardson 	}
100899a2dd95SBruce Richardson 
100999a2dd95SBruce Richardson 	rte_mempool_free(sw->tim_pool);
101099a2dd95SBruce Richardson 	rte_free(sw);
101199a2dd95SBruce Richardson 	adapter->data->adapter_priv = NULL;
101299a2dd95SBruce Richardson 
101399a2dd95SBruce Richardson 	return 0;
101499a2dd95SBruce Richardson }
101599a2dd95SBruce Richardson 
101699a2dd95SBruce Richardson static inline int32_t
101799a2dd95SBruce Richardson get_mapped_count_for_service(uint32_t service_id)
101899a2dd95SBruce Richardson {
101999a2dd95SBruce Richardson 	int32_t core_count, i, mapped_count = 0;
102099a2dd95SBruce Richardson 	uint32_t lcore_arr[RTE_MAX_LCORE];
102199a2dd95SBruce Richardson 
102299a2dd95SBruce Richardson 	core_count = rte_service_lcore_list(lcore_arr, RTE_MAX_LCORE);
102399a2dd95SBruce Richardson 
102499a2dd95SBruce Richardson 	for (i = 0; i < core_count; i++)
102599a2dd95SBruce Richardson 		if (rte_service_map_lcore_get(service_id, lcore_arr[i]) == 1)
102699a2dd95SBruce Richardson 			mapped_count++;
102799a2dd95SBruce Richardson 
102899a2dd95SBruce Richardson 	return mapped_count;
102999a2dd95SBruce Richardson }
103099a2dd95SBruce Richardson 
103199a2dd95SBruce Richardson static int
103299a2dd95SBruce Richardson swtim_start(const struct rte_event_timer_adapter *adapter)
103399a2dd95SBruce Richardson {
103499a2dd95SBruce Richardson 	int mapped_count;
103599a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
103699a2dd95SBruce Richardson 
103799a2dd95SBruce Richardson 	/* Mapping the service to more than one service core can introduce
103899a2dd95SBruce Richardson 	 * delays while one thread is waiting to acquire a lock, so only allow
103999a2dd95SBruce Richardson 	 * one core to be mapped to the service.
104099a2dd95SBruce Richardson 	 *
104199a2dd95SBruce Richardson 	 * Note: the service could be modified such that it spreads cores to
104299a2dd95SBruce Richardson 	 * poll over multiple service instances.
104399a2dd95SBruce Richardson 	 */
104499a2dd95SBruce Richardson 	mapped_count = get_mapped_count_for_service(sw->service_id);
104599a2dd95SBruce Richardson 
104699a2dd95SBruce Richardson 	if (mapped_count != 1)
104799a2dd95SBruce Richardson 		return mapped_count < 1 ? -ENOENT : -ENOTSUP;
104899a2dd95SBruce Richardson 
104999a2dd95SBruce Richardson 	return rte_service_component_runstate_set(sw->service_id, 1);
105099a2dd95SBruce Richardson }
105199a2dd95SBruce Richardson 
105299a2dd95SBruce Richardson static int
105399a2dd95SBruce Richardson swtim_stop(const struct rte_event_timer_adapter *adapter)
105499a2dd95SBruce Richardson {
105599a2dd95SBruce Richardson 	int ret;
105699a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
105799a2dd95SBruce Richardson 
105899a2dd95SBruce Richardson 	ret = rte_service_component_runstate_set(sw->service_id, 0);
105999a2dd95SBruce Richardson 	if (ret < 0)
106099a2dd95SBruce Richardson 		return ret;
106199a2dd95SBruce Richardson 
106299a2dd95SBruce Richardson 	/* Wait for the service to complete its final iteration */
106399a2dd95SBruce Richardson 	while (rte_service_may_be_active(sw->service_id))
106499a2dd95SBruce Richardson 		rte_pause();
106599a2dd95SBruce Richardson 
106699a2dd95SBruce Richardson 	return 0;
106799a2dd95SBruce Richardson }
106899a2dd95SBruce Richardson 
106999a2dd95SBruce Richardson static void
107099a2dd95SBruce Richardson swtim_get_info(const struct rte_event_timer_adapter *adapter,
107199a2dd95SBruce Richardson 		struct rte_event_timer_adapter_info *adapter_info)
107299a2dd95SBruce Richardson {
107399a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
107499a2dd95SBruce Richardson 	adapter_info->min_resolution_ns = sw->timer_tick_ns;
107599a2dd95SBruce Richardson 	adapter_info->max_tmo_ns = sw->max_tmo_ns;
107699a2dd95SBruce Richardson }
107799a2dd95SBruce Richardson 
107899a2dd95SBruce Richardson static int
107999a2dd95SBruce Richardson swtim_stats_get(const struct rte_event_timer_adapter *adapter,
108099a2dd95SBruce Richardson 		struct rte_event_timer_adapter_stats *stats)
108199a2dd95SBruce Richardson {
108299a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
108399a2dd95SBruce Richardson 	*stats = sw->stats; /* structure copy */
108499a2dd95SBruce Richardson 	return 0;
108599a2dd95SBruce Richardson }
108699a2dd95SBruce Richardson 
108799a2dd95SBruce Richardson static int
108899a2dd95SBruce Richardson swtim_stats_reset(const struct rte_event_timer_adapter *adapter)
108999a2dd95SBruce Richardson {
109099a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
109199a2dd95SBruce Richardson 	memset(&sw->stats, 0, sizeof(sw->stats));
109299a2dd95SBruce Richardson 	return 0;
109399a2dd95SBruce Richardson }
109499a2dd95SBruce Richardson 
10950727ff34SErik Gabriel Carrillo static int
10960727ff34SErik Gabriel Carrillo swtim_remaining_ticks_get(const struct rte_event_timer_adapter *adapter,
10970727ff34SErik Gabriel Carrillo 			  const struct rte_event_timer *evtim,
10980727ff34SErik Gabriel Carrillo 			  uint64_t *ticks_remaining)
10990727ff34SErik Gabriel Carrillo {
11000727ff34SErik Gabriel Carrillo 	uint64_t nsecs_per_adapter_tick, opaque, cycles_remaining;
11010727ff34SErik Gabriel Carrillo 	enum rte_event_timer_state n_state;
11020727ff34SErik Gabriel Carrillo 	double nsecs_per_cycle;
11030727ff34SErik Gabriel Carrillo 	struct rte_timer *tim;
11040727ff34SErik Gabriel Carrillo 	uint64_t cur_cycles;
11050727ff34SErik Gabriel Carrillo 
11060727ff34SErik Gabriel Carrillo 	/* Check that timer is armed */
11070727ff34SErik Gabriel Carrillo 	n_state = __atomic_load_n(&evtim->state, __ATOMIC_ACQUIRE);
11080727ff34SErik Gabriel Carrillo 	if (n_state != RTE_EVENT_TIMER_ARMED)
11090727ff34SErik Gabriel Carrillo 		return -EINVAL;
11100727ff34SErik Gabriel Carrillo 
11110727ff34SErik Gabriel Carrillo 	opaque = evtim->impl_opaque[0];
11120727ff34SErik Gabriel Carrillo 	tim = (struct rte_timer *)(uintptr_t)opaque;
11130727ff34SErik Gabriel Carrillo 
11140727ff34SErik Gabriel Carrillo 	cur_cycles = rte_get_timer_cycles();
11150727ff34SErik Gabriel Carrillo 	if (cur_cycles > tim->expire) {
11160727ff34SErik Gabriel Carrillo 		*ticks_remaining = 0;
11170727ff34SErik Gabriel Carrillo 		return 0;
11180727ff34SErik Gabriel Carrillo 	}
11190727ff34SErik Gabriel Carrillo 
11200727ff34SErik Gabriel Carrillo 	cycles_remaining = tim->expire - cur_cycles;
11210727ff34SErik Gabriel Carrillo 	nsecs_per_cycle = (double)NSECPERSEC / rte_get_timer_hz();
11220727ff34SErik Gabriel Carrillo 	nsecs_per_adapter_tick = adapter->data->conf.timer_tick_ns;
11230727ff34SErik Gabriel Carrillo 
11240727ff34SErik Gabriel Carrillo 	*ticks_remaining = (uint64_t)ceil((cycles_remaining * nsecs_per_cycle) /
11250727ff34SErik Gabriel Carrillo 					  nsecs_per_adapter_tick);
11260727ff34SErik Gabriel Carrillo 
11270727ff34SErik Gabriel Carrillo 	return 0;
11280727ff34SErik Gabriel Carrillo }
11290727ff34SErik Gabriel Carrillo 
113099a2dd95SBruce Richardson static uint16_t
113199a2dd95SBruce Richardson __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
113299a2dd95SBruce Richardson 		struct rte_event_timer **evtims,
113399a2dd95SBruce Richardson 		uint16_t nb_evtims)
113499a2dd95SBruce Richardson {
113599a2dd95SBruce Richardson 	int i, ret;
113699a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
113799a2dd95SBruce Richardson 	uint32_t lcore_id = rte_lcore_id();
113899a2dd95SBruce Richardson 	struct rte_timer *tim, *tims[nb_evtims];
113999a2dd95SBruce Richardson 	uint64_t cycles;
114099a2dd95SBruce Richardson 	int n_lcores;
114199a2dd95SBruce Richardson 	/* Timer list for this lcore is not in use. */
114299a2dd95SBruce Richardson 	uint16_t exp_state = 0;
114399a2dd95SBruce Richardson 	enum rte_event_timer_state n_state;
11443d9d8adfSNaga Harish K S V 	enum rte_timer_type type = SINGLE;
114599a2dd95SBruce Richardson 
114699a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
114799a2dd95SBruce Richardson 	/* Check that the service is running. */
114899a2dd95SBruce Richardson 	if (rte_service_runstate_get(adapter->data->service_id) != 1) {
114999a2dd95SBruce Richardson 		rte_errno = EINVAL;
115099a2dd95SBruce Richardson 		return 0;
115199a2dd95SBruce Richardson 	}
115299a2dd95SBruce Richardson #endif
115399a2dd95SBruce Richardson 
115499a2dd95SBruce Richardson 	/* Adjust lcore_id if non-EAL thread. Arbitrarily pick the timer list of
115599a2dd95SBruce Richardson 	 * the highest lcore to insert such timers into
115699a2dd95SBruce Richardson 	 */
115799a2dd95SBruce Richardson 	if (lcore_id == LCORE_ID_ANY)
115899a2dd95SBruce Richardson 		lcore_id = RTE_MAX_LCORE - 1;
115999a2dd95SBruce Richardson 
116099a2dd95SBruce Richardson 	/* If this is the first time we're arming an event timer on this lcore,
116199a2dd95SBruce Richardson 	 * mark this lcore as "in use"; this will cause the service
116299a2dd95SBruce Richardson 	 * function to process the timer list that corresponds to this lcore.
116399a2dd95SBruce Richardson 	 * The atomic compare-and-swap operation can prevent the race condition
116499a2dd95SBruce Richardson 	 * on in_use flag between multiple non-EAL threads.
116599a2dd95SBruce Richardson 	 */
116699a2dd95SBruce Richardson 	if (unlikely(__atomic_compare_exchange_n(&sw->in_use[lcore_id].v,
116799a2dd95SBruce Richardson 			&exp_state, 1, 0,
116899a2dd95SBruce Richardson 			__ATOMIC_RELAXED, __ATOMIC_RELAXED))) {
116999a2dd95SBruce Richardson 		EVTIM_LOG_DBG("Adding lcore id = %u to list of lcores to poll",
117099a2dd95SBruce Richardson 			      lcore_id);
117199a2dd95SBruce Richardson 		n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
117299a2dd95SBruce Richardson 					     __ATOMIC_RELAXED);
117399a2dd95SBruce Richardson 		__atomic_store_n(&sw->poll_lcores[n_lcores], lcore_id,
117499a2dd95SBruce Richardson 				__ATOMIC_RELAXED);
117599a2dd95SBruce Richardson 	}
117699a2dd95SBruce Richardson 
117799a2dd95SBruce Richardson 	ret = rte_mempool_get_bulk(sw->tim_pool, (void **)tims,
117899a2dd95SBruce Richardson 				   nb_evtims);
117999a2dd95SBruce Richardson 	if (ret < 0) {
118099a2dd95SBruce Richardson 		rte_errno = ENOSPC;
118199a2dd95SBruce Richardson 		return 0;
118299a2dd95SBruce Richardson 	}
118399a2dd95SBruce Richardson 
11843d9d8adfSNaga Harish K S V 	/* update timer type for periodic adapter */
11853d9d8adfSNaga Harish K S V 	type = get_timer_type(adapter);
11863d9d8adfSNaga Harish K S V 
118799a2dd95SBruce Richardson 	for (i = 0; i < nb_evtims; i++) {
118899a2dd95SBruce Richardson 		n_state = __atomic_load_n(&evtims[i]->state, __ATOMIC_ACQUIRE);
118999a2dd95SBruce Richardson 		if (n_state == RTE_EVENT_TIMER_ARMED) {
119099a2dd95SBruce Richardson 			rte_errno = EALREADY;
119199a2dd95SBruce Richardson 			break;
119299a2dd95SBruce Richardson 		} else if (!(n_state == RTE_EVENT_TIMER_NOT_ARMED ||
119399a2dd95SBruce Richardson 			     n_state == RTE_EVENT_TIMER_CANCELED)) {
119499a2dd95SBruce Richardson 			rte_errno = EINVAL;
119599a2dd95SBruce Richardson 			break;
119699a2dd95SBruce Richardson 		}
119799a2dd95SBruce Richardson 
119899a2dd95SBruce Richardson 		ret = check_timeout(evtims[i], adapter);
119999a2dd95SBruce Richardson 		if (unlikely(ret == -1)) {
120099a2dd95SBruce Richardson 			__atomic_store_n(&evtims[i]->state,
120199a2dd95SBruce Richardson 					RTE_EVENT_TIMER_ERROR_TOOLATE,
120299a2dd95SBruce Richardson 					__ATOMIC_RELAXED);
120399a2dd95SBruce Richardson 			rte_errno = EINVAL;
120499a2dd95SBruce Richardson 			break;
120599a2dd95SBruce Richardson 		} else if (unlikely(ret == -2)) {
120699a2dd95SBruce Richardson 			__atomic_store_n(&evtims[i]->state,
120799a2dd95SBruce Richardson 					RTE_EVENT_TIMER_ERROR_TOOEARLY,
120899a2dd95SBruce Richardson 					__ATOMIC_RELAXED);
120999a2dd95SBruce Richardson 			rte_errno = EINVAL;
121099a2dd95SBruce Richardson 			break;
121199a2dd95SBruce Richardson 		}
121299a2dd95SBruce Richardson 
121399a2dd95SBruce Richardson 		if (unlikely(check_destination_event_queue(evtims[i],
121499a2dd95SBruce Richardson 							   adapter) < 0)) {
121599a2dd95SBruce Richardson 			__atomic_store_n(&evtims[i]->state,
121699a2dd95SBruce Richardson 					RTE_EVENT_TIMER_ERROR,
121799a2dd95SBruce Richardson 					__ATOMIC_RELAXED);
121899a2dd95SBruce Richardson 			rte_errno = EINVAL;
121999a2dd95SBruce Richardson 			break;
122099a2dd95SBruce Richardson 		}
122199a2dd95SBruce Richardson 
122299a2dd95SBruce Richardson 		tim = tims[i];
122399a2dd95SBruce Richardson 		rte_timer_init(tim);
122499a2dd95SBruce Richardson 
122599a2dd95SBruce Richardson 		evtims[i]->impl_opaque[0] = (uintptr_t)tim;
122699a2dd95SBruce Richardson 		evtims[i]->impl_opaque[1] = (uintptr_t)adapter;
122799a2dd95SBruce Richardson 
122899a2dd95SBruce Richardson 		cycles = get_timeout_cycles(evtims[i], adapter);
122999a2dd95SBruce Richardson 		ret = rte_timer_alt_reset(sw->timer_data_id, tim, cycles,
12303d9d8adfSNaga Harish K S V 					  type, lcore_id, NULL, evtims[i]);
123199a2dd95SBruce Richardson 		if (ret < 0) {
123299a2dd95SBruce Richardson 			/* tim was in RUNNING or CONFIG state */
123399a2dd95SBruce Richardson 			__atomic_store_n(&evtims[i]->state,
123499a2dd95SBruce Richardson 					RTE_EVENT_TIMER_ERROR,
123599a2dd95SBruce Richardson 					__ATOMIC_RELEASE);
123699a2dd95SBruce Richardson 			break;
123799a2dd95SBruce Richardson 		}
123899a2dd95SBruce Richardson 
123999a2dd95SBruce Richardson 		EVTIM_LOG_DBG("armed an event timer");
124099a2dd95SBruce Richardson 		/* RELEASE ordering guarantees the adapter specific value
124199a2dd95SBruce Richardson 		 * changes observed before the update of state.
124299a2dd95SBruce Richardson 		 */
124399a2dd95SBruce Richardson 		__atomic_store_n(&evtims[i]->state, RTE_EVENT_TIMER_ARMED,
124499a2dd95SBruce Richardson 				__ATOMIC_RELEASE);
124599a2dd95SBruce Richardson 	}
124699a2dd95SBruce Richardson 
124799a2dd95SBruce Richardson 	if (i < nb_evtims)
124899a2dd95SBruce Richardson 		rte_mempool_put_bulk(sw->tim_pool,
124999a2dd95SBruce Richardson 				     (void **)&tims[i], nb_evtims - i);
125099a2dd95SBruce Richardson 
125199a2dd95SBruce Richardson 	return i;
125299a2dd95SBruce Richardson }
125399a2dd95SBruce Richardson 
125499a2dd95SBruce Richardson static uint16_t
125599a2dd95SBruce Richardson swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
125699a2dd95SBruce Richardson 		struct rte_event_timer **evtims,
125799a2dd95SBruce Richardson 		uint16_t nb_evtims)
125899a2dd95SBruce Richardson {
125999a2dd95SBruce Richardson 	return __swtim_arm_burst(adapter, evtims, nb_evtims);
126099a2dd95SBruce Richardson }
126199a2dd95SBruce Richardson 
126299a2dd95SBruce Richardson static uint16_t
126399a2dd95SBruce Richardson swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
126499a2dd95SBruce Richardson 		   struct rte_event_timer **evtims,
126599a2dd95SBruce Richardson 		   uint16_t nb_evtims)
126699a2dd95SBruce Richardson {
126799a2dd95SBruce Richardson 	int i, ret;
126899a2dd95SBruce Richardson 	struct rte_timer *timp;
126999a2dd95SBruce Richardson 	uint64_t opaque;
127099a2dd95SBruce Richardson 	struct swtim *sw = swtim_pmd_priv(adapter);
127199a2dd95SBruce Richardson 	enum rte_event_timer_state n_state;
127299a2dd95SBruce Richardson 
127399a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
127499a2dd95SBruce Richardson 	/* Check that the service is running. */
127599a2dd95SBruce Richardson 	if (rte_service_runstate_get(adapter->data->service_id) != 1) {
127699a2dd95SBruce Richardson 		rte_errno = EINVAL;
127799a2dd95SBruce Richardson 		return 0;
127899a2dd95SBruce Richardson 	}
127999a2dd95SBruce Richardson #endif
128099a2dd95SBruce Richardson 
128199a2dd95SBruce Richardson 	for (i = 0; i < nb_evtims; i++) {
128299a2dd95SBruce Richardson 		/* Don't modify the event timer state in these cases */
128399a2dd95SBruce Richardson 		/* ACQUIRE ordering guarantees the access of implementation
128499a2dd95SBruce Richardson 		 * specific opaque data under the correct state.
128599a2dd95SBruce Richardson 		 */
128699a2dd95SBruce Richardson 		n_state = __atomic_load_n(&evtims[i]->state, __ATOMIC_ACQUIRE);
128799a2dd95SBruce Richardson 		if (n_state == RTE_EVENT_TIMER_CANCELED) {
128899a2dd95SBruce Richardson 			rte_errno = EALREADY;
128999a2dd95SBruce Richardson 			break;
129099a2dd95SBruce Richardson 		} else if (n_state != RTE_EVENT_TIMER_ARMED) {
129199a2dd95SBruce Richardson 			rte_errno = EINVAL;
129299a2dd95SBruce Richardson 			break;
129399a2dd95SBruce Richardson 		}
129499a2dd95SBruce Richardson 
129599a2dd95SBruce Richardson 		opaque = evtims[i]->impl_opaque[0];
129699a2dd95SBruce Richardson 		timp = (struct rte_timer *)(uintptr_t)opaque;
129799a2dd95SBruce Richardson 		RTE_ASSERT(timp != NULL);
129899a2dd95SBruce Richardson 
129999a2dd95SBruce Richardson 		ret = rte_timer_alt_stop(sw->timer_data_id, timp);
130099a2dd95SBruce Richardson 		if (ret < 0) {
130199a2dd95SBruce Richardson 			/* Timer is running or being configured */
130299a2dd95SBruce Richardson 			rte_errno = EAGAIN;
130399a2dd95SBruce Richardson 			break;
130499a2dd95SBruce Richardson 		}
130599a2dd95SBruce Richardson 
130699a2dd95SBruce Richardson 		rte_mempool_put(sw->tim_pool, (void **)timp);
130799a2dd95SBruce Richardson 
130899a2dd95SBruce Richardson 		/* The RELEASE ordering here pairs with atomic ordering
130999a2dd95SBruce Richardson 		 * to make sure the state update data observed between
131099a2dd95SBruce Richardson 		 * threads.
131199a2dd95SBruce Richardson 		 */
131299a2dd95SBruce Richardson 		__atomic_store_n(&evtims[i]->state, RTE_EVENT_TIMER_CANCELED,
131399a2dd95SBruce Richardson 				__ATOMIC_RELEASE);
131499a2dd95SBruce Richardson 	}
131599a2dd95SBruce Richardson 
131699a2dd95SBruce Richardson 	return i;
131799a2dd95SBruce Richardson }
131899a2dd95SBruce Richardson 
131999a2dd95SBruce Richardson static uint16_t
132099a2dd95SBruce Richardson swtim_arm_tmo_tick_burst(const struct rte_event_timer_adapter *adapter,
132199a2dd95SBruce Richardson 			 struct rte_event_timer **evtims,
132299a2dd95SBruce Richardson 			 uint64_t timeout_ticks,
132399a2dd95SBruce Richardson 			 uint16_t nb_evtims)
132499a2dd95SBruce Richardson {
132599a2dd95SBruce Richardson 	int i;
132699a2dd95SBruce Richardson 
132799a2dd95SBruce Richardson 	for (i = 0; i < nb_evtims; i++)
132899a2dd95SBruce Richardson 		evtims[i]->timeout_ticks = timeout_ticks;
132999a2dd95SBruce Richardson 
133099a2dd95SBruce Richardson 	return __swtim_arm_burst(adapter, evtims, nb_evtims);
133199a2dd95SBruce Richardson }
133299a2dd95SBruce Richardson 
133353548ad3SPavan Nikhilesh static const struct event_timer_adapter_ops swtim_ops = {
133499a2dd95SBruce Richardson 	.init = swtim_init,
133599a2dd95SBruce Richardson 	.uninit = swtim_uninit,
133699a2dd95SBruce Richardson 	.start = swtim_start,
133799a2dd95SBruce Richardson 	.stop = swtim_stop,
133899a2dd95SBruce Richardson 	.get_info = swtim_get_info,
133999a2dd95SBruce Richardson 	.stats_get = swtim_stats_get,
134099a2dd95SBruce Richardson 	.stats_reset = swtim_stats_reset,
134199a2dd95SBruce Richardson 	.arm_burst = swtim_arm_burst,
134299a2dd95SBruce Richardson 	.arm_tmo_tick_burst = swtim_arm_tmo_tick_burst,
134399a2dd95SBruce Richardson 	.cancel_burst = swtim_cancel_burst,
13440727ff34SErik Gabriel Carrillo 	.remaining_ticks_get = swtim_remaining_ticks_get,
134599a2dd95SBruce Richardson };
1346791dfec2SAnkur Dwivedi 
1347791dfec2SAnkur Dwivedi static int
1348791dfec2SAnkur Dwivedi handle_ta_info(const char *cmd __rte_unused, const char *params,
1349791dfec2SAnkur Dwivedi 		struct rte_tel_data *d)
1350791dfec2SAnkur Dwivedi {
1351791dfec2SAnkur Dwivedi 	struct rte_event_timer_adapter_info adapter_info;
1352791dfec2SAnkur Dwivedi 	struct rte_event_timer_adapter *adapter;
1353791dfec2SAnkur Dwivedi 	uint16_t adapter_id;
1354791dfec2SAnkur Dwivedi 	int ret;
1355791dfec2SAnkur Dwivedi 
1356791dfec2SAnkur Dwivedi 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
1357791dfec2SAnkur Dwivedi 		return -1;
1358791dfec2SAnkur Dwivedi 
1359791dfec2SAnkur Dwivedi 	adapter_id = atoi(params);
1360791dfec2SAnkur Dwivedi 
1361791dfec2SAnkur Dwivedi 	if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
1362791dfec2SAnkur Dwivedi 		EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
1363791dfec2SAnkur Dwivedi 		return -EINVAL;
1364791dfec2SAnkur Dwivedi 	}
1365791dfec2SAnkur Dwivedi 
1366791dfec2SAnkur Dwivedi 	adapter = &adapters[adapter_id];
1367791dfec2SAnkur Dwivedi 
1368791dfec2SAnkur Dwivedi 	ret = rte_event_timer_adapter_get_info(adapter, &adapter_info);
1369791dfec2SAnkur Dwivedi 	if (ret < 0) {
1370791dfec2SAnkur Dwivedi 		EVTIM_LOG_ERR("Failed to get info for timer adapter id %u", adapter_id);
1371791dfec2SAnkur Dwivedi 		return ret;
1372791dfec2SAnkur Dwivedi 	}
1373791dfec2SAnkur Dwivedi 
1374791dfec2SAnkur Dwivedi 	rte_tel_data_start_dict(d);
1375*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
1376*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "min_resolution_ns",
1377*af0785a2SBruce Richardson 				   adapter_info.min_resolution_ns);
1378*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "max_tmo_ns", adapter_info.max_tmo_ns);
1379*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "event_dev_id",
1380*af0785a2SBruce Richardson 				   adapter_info.conf.event_dev_id);
1381*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "socket_id",
1382*af0785a2SBruce Richardson 				   adapter_info.conf.socket_id);
1383*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "clk_src", adapter_info.conf.clk_src);
1384*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "timer_tick_ns",
1385*af0785a2SBruce Richardson 				   adapter_info.conf.timer_tick_ns);
1386*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "nb_timers",
1387*af0785a2SBruce Richardson 				   adapter_info.conf.nb_timers);
1388*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "flags", adapter_info.conf.flags);
1389791dfec2SAnkur Dwivedi 
1390791dfec2SAnkur Dwivedi 	return 0;
1391791dfec2SAnkur Dwivedi }
1392791dfec2SAnkur Dwivedi 
1393791dfec2SAnkur Dwivedi static int
1394791dfec2SAnkur Dwivedi handle_ta_stats(const char *cmd __rte_unused, const char *params,
1395791dfec2SAnkur Dwivedi 		struct rte_tel_data *d)
1396791dfec2SAnkur Dwivedi {
1397791dfec2SAnkur Dwivedi 	struct rte_event_timer_adapter_stats stats;
1398791dfec2SAnkur Dwivedi 	struct rte_event_timer_adapter *adapter;
1399791dfec2SAnkur Dwivedi 	uint16_t adapter_id;
1400791dfec2SAnkur Dwivedi 	int ret;
1401791dfec2SAnkur Dwivedi 
1402791dfec2SAnkur Dwivedi 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
1403791dfec2SAnkur Dwivedi 		return -1;
1404791dfec2SAnkur Dwivedi 
1405791dfec2SAnkur Dwivedi 	adapter_id = atoi(params);
1406791dfec2SAnkur Dwivedi 
1407791dfec2SAnkur Dwivedi 	if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
1408791dfec2SAnkur Dwivedi 		EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
1409791dfec2SAnkur Dwivedi 		return -EINVAL;
1410791dfec2SAnkur Dwivedi 	}
1411791dfec2SAnkur Dwivedi 
1412791dfec2SAnkur Dwivedi 	adapter = &adapters[adapter_id];
1413791dfec2SAnkur Dwivedi 
1414791dfec2SAnkur Dwivedi 	ret = rte_event_timer_adapter_stats_get(adapter, &stats);
1415791dfec2SAnkur Dwivedi 	if (ret < 0) {
1416791dfec2SAnkur Dwivedi 		EVTIM_LOG_ERR("Failed to get stats for timer adapter id %u", adapter_id);
1417791dfec2SAnkur Dwivedi 		return ret;
1418791dfec2SAnkur Dwivedi 	}
1419791dfec2SAnkur Dwivedi 
1420791dfec2SAnkur Dwivedi 	rte_tel_data_start_dict(d);
1421*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
1422*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "evtim_exp_count",
1423*af0785a2SBruce Richardson 				   stats.evtim_exp_count);
1424*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "ev_enq_count", stats.ev_enq_count);
1425*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "ev_inv_count", stats.ev_inv_count);
1426*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "evtim_retry_count",
1427*af0785a2SBruce Richardson 				   stats.evtim_retry_count);
1428*af0785a2SBruce Richardson 	rte_tel_data_add_dict_uint(d, "adapter_tick_count",
1429*af0785a2SBruce Richardson 				   stats.adapter_tick_count);
1430791dfec2SAnkur Dwivedi 
1431791dfec2SAnkur Dwivedi 	return 0;
1432791dfec2SAnkur Dwivedi }
1433791dfec2SAnkur Dwivedi 
1434791dfec2SAnkur Dwivedi RTE_INIT(ta_init_telemetry)
1435791dfec2SAnkur Dwivedi {
1436791dfec2SAnkur Dwivedi 	rte_telemetry_register_cmd("/eventdev/ta_info",
1437791dfec2SAnkur Dwivedi 		handle_ta_info,
1438791dfec2SAnkur Dwivedi 		"Returns Timer adapter info. Parameter: Timer adapter id");
1439791dfec2SAnkur Dwivedi 
1440791dfec2SAnkur Dwivedi 	rte_telemetry_register_cmd("/eventdev/ta_stats",
1441791dfec2SAnkur Dwivedi 		handle_ta_stats,
1442791dfec2SAnkur Dwivedi 		"Returns Timer adapter stats. Parameter: Timer adapter id");
1443791dfec2SAnkur Dwivedi }
1444