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>
9e9fd1ebfSTyler Retzlaff #include <stdalign.h>
1099a2dd95SBruce Richardson #include <stdbool.h>
1172b452c5SDmitry Kozlyuk #include <stdlib.h>
120727ff34SErik Gabriel Carrillo #include <math.h>
1399a2dd95SBruce Richardson
1499a2dd95SBruce Richardson #include <rte_memzone.h>
1599a2dd95SBruce Richardson #include <rte_errno.h>
1699a2dd95SBruce Richardson #include <rte_malloc.h>
1799a2dd95SBruce Richardson #include <rte_mempool.h>
1899a2dd95SBruce Richardson #include <rte_common.h>
1999a2dd95SBruce Richardson #include <rte_timer.h>
2099a2dd95SBruce Richardson #include <rte_service_component.h>
21791dfec2SAnkur Dwivedi #include <rte_telemetry.h>
2213aba5f8SErik Gabriel Carrillo #include <rte_reciprocal.h>
2399a2dd95SBruce Richardson
2453548ad3SPavan Nikhilesh #include "event_timer_adapter_pmd.h"
2599a2dd95SBruce Richardson #include "eventdev_pmd.h"
2699a2dd95SBruce Richardson #include "rte_event_timer_adapter.h"
2753548ad3SPavan Nikhilesh #include "rte_eventdev.h"
28f26f2ca6SPavan Nikhilesh #include "eventdev_trace.h"
2999a2dd95SBruce Richardson
3099a2dd95SBruce Richardson #define DATA_MZ_NAME_MAX_LEN 64
3199a2dd95SBruce Richardson #define DATA_MZ_NAME_FORMAT "rte_event_timer_adapter_data_%d"
3299a2dd95SBruce Richardson
33eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_logtype, adapter.timer, NOTICE);
3497433132SDavid Marchand #define RTE_LOGTYPE_EVTIM evtim_logtype
35eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_buffer_logtype, adapter.timer, NOTICE);
3697433132SDavid Marchand #define RTE_LOGTYPE_EVTIM_BUF evtim_buffer_logtype
37eeded204SDavid Marchand RTE_LOG_REGISTER_SUFFIX(evtim_svc_logtype, adapter.timer.svc, NOTICE);
3897433132SDavid Marchand #define RTE_LOGTYPE_EVTIM_SVC evtim_svc_logtype
3999a2dd95SBruce Richardson
40f3f3a917SPavan Nikhilesh static struct rte_event_timer_adapter *adapters;
4199a2dd95SBruce Richardson
4253548ad3SPavan Nikhilesh static const struct event_timer_adapter_ops swtim_ops;
4399a2dd95SBruce Richardson
4499a2dd95SBruce Richardson #define EVTIM_LOG(level, logtype, ...) \
450f1dc8cbSTyler Retzlaff RTE_LOG_LINE_PREFIX(level, logtype, \
460f1dc8cbSTyler Retzlaff "EVTIMER: %s() line %u: ", __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
4799a2dd95SBruce Richardson
4897433132SDavid Marchand #define EVTIM_LOG_ERR(...) EVTIM_LOG(ERR, EVTIM, __VA_ARGS__)
4999a2dd95SBruce Richardson
5099a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
5199a2dd95SBruce Richardson #define EVTIM_LOG_DBG(...) \
5297433132SDavid Marchand EVTIM_LOG(DEBUG, EVTIM, __VA_ARGS__)
5399a2dd95SBruce Richardson #define EVTIM_BUF_LOG_DBG(...) \
5497433132SDavid Marchand EVTIM_LOG(DEBUG, EVTIM_BUF, __VA_ARGS__)
5599a2dd95SBruce Richardson #define EVTIM_SVC_LOG_DBG(...) \
5697433132SDavid Marchand EVTIM_LOG(DEBUG, EVTIM_SVC, __VA_ARGS__)
5799a2dd95SBruce Richardson #else
5899a2dd95SBruce Richardson #define EVTIM_LOG_DBG(...) (void)0
5999a2dd95SBruce Richardson #define EVTIM_BUF_LOG_DBG(...) (void)0
6099a2dd95SBruce Richardson #define EVTIM_SVC_LOG_DBG(...) (void)0
6199a2dd95SBruce Richardson #endif
6299a2dd95SBruce Richardson
633d9d8adfSNaga Harish K S V static inline enum rte_timer_type
get_timer_type(const struct rte_event_timer_adapter * adapter)643d9d8adfSNaga Harish K S V get_timer_type(const struct rte_event_timer_adapter *adapter)
653d9d8adfSNaga Harish K S V {
663d9d8adfSNaga Harish K S V return (adapter->data->conf.flags &
673d9d8adfSNaga Harish K S V RTE_EVENT_TIMER_ADAPTER_F_PERIODIC) ?
683d9d8adfSNaga Harish K S V PERIODICAL : SINGLE;
693d9d8adfSNaga Harish K S V }
703d9d8adfSNaga Harish K S V
7199a2dd95SBruce Richardson static int
default_port_conf_cb(uint16_t id,uint8_t event_dev_id,uint8_t * event_port_id,void * conf_arg)7299a2dd95SBruce Richardson default_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id,
7399a2dd95SBruce Richardson void *conf_arg)
7499a2dd95SBruce Richardson {
7599a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter;
7699a2dd95SBruce Richardson struct rte_eventdev *dev;
7799a2dd95SBruce Richardson struct rte_event_dev_config dev_conf;
7899a2dd95SBruce Richardson struct rte_event_port_conf *port_conf, def_port_conf = {0};
7999a2dd95SBruce Richardson int started;
8099a2dd95SBruce Richardson uint8_t port_id;
8199a2dd95SBruce Richardson uint8_t dev_id;
8299a2dd95SBruce Richardson int ret;
8399a2dd95SBruce Richardson
8499a2dd95SBruce Richardson RTE_SET_USED(event_dev_id);
8599a2dd95SBruce Richardson
8699a2dd95SBruce Richardson adapter = &adapters[id];
8799a2dd95SBruce Richardson dev = &rte_eventdevs[adapter->data->event_dev_id];
8899a2dd95SBruce Richardson dev_id = dev->data->dev_id;
8999a2dd95SBruce Richardson dev_conf = dev->data->dev_conf;
9099a2dd95SBruce Richardson
9199a2dd95SBruce Richardson started = dev->data->dev_started;
9299a2dd95SBruce Richardson if (started)
9399a2dd95SBruce Richardson rte_event_dev_stop(dev_id);
9499a2dd95SBruce Richardson
9599a2dd95SBruce Richardson port_id = dev_conf.nb_event_ports;
96850ae162SNaga Harish K S V if (conf_arg != NULL)
97850ae162SNaga Harish K S V port_conf = conf_arg;
98850ae162SNaga Harish K S V else {
99850ae162SNaga Harish K S V port_conf = &def_port_conf;
100850ae162SNaga Harish K S V ret = rte_event_port_default_conf_get(dev_id, (port_id - 1),
101850ae162SNaga Harish K S V port_conf);
102850ae162SNaga Harish K S V if (ret < 0)
103850ae162SNaga Harish K S V return ret;
104850ae162SNaga Harish K S V }
105850ae162SNaga Harish K S V
10699a2dd95SBruce Richardson dev_conf.nb_event_ports += 1;
107850ae162SNaga Harish K S V if (port_conf->event_port_cfg & RTE_EVENT_PORT_CFG_SINGLE_LINK)
108850ae162SNaga Harish K S V dev_conf.nb_single_link_event_port_queues += 1;
109850ae162SNaga Harish K S V
11099a2dd95SBruce Richardson ret = rte_event_dev_configure(dev_id, &dev_conf);
11199a2dd95SBruce Richardson if (ret < 0) {
112ae282b06SDavid Marchand EVTIM_LOG_ERR("failed to configure event dev %u", dev_id);
11399a2dd95SBruce Richardson if (started)
11499a2dd95SBruce Richardson if (rte_event_dev_start(dev_id))
11599a2dd95SBruce Richardson return -EIO;
11699a2dd95SBruce Richardson
11799a2dd95SBruce Richardson return ret;
11899a2dd95SBruce Richardson }
11999a2dd95SBruce Richardson
12099a2dd95SBruce Richardson ret = rte_event_port_setup(dev_id, port_id, port_conf);
12199a2dd95SBruce Richardson if (ret < 0) {
122ae282b06SDavid Marchand EVTIM_LOG_ERR("failed to setup event port %u on event dev %u",
12399a2dd95SBruce Richardson port_id, dev_id);
12499a2dd95SBruce Richardson return ret;
12599a2dd95SBruce Richardson }
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson *event_port_id = port_id;
12899a2dd95SBruce Richardson
12999a2dd95SBruce Richardson if (started)
13099a2dd95SBruce Richardson ret = rte_event_dev_start(dev_id);
13199a2dd95SBruce Richardson
13299a2dd95SBruce Richardson return ret;
13399a2dd95SBruce Richardson }
13499a2dd95SBruce Richardson
13599a2dd95SBruce Richardson struct rte_event_timer_adapter *
rte_event_timer_adapter_create(const struct rte_event_timer_adapter_conf * conf)13699a2dd95SBruce Richardson rte_event_timer_adapter_create(const struct rte_event_timer_adapter_conf *conf)
13799a2dd95SBruce Richardson {
13899a2dd95SBruce Richardson return rte_event_timer_adapter_create_ext(conf, default_port_conf_cb,
13999a2dd95SBruce Richardson NULL);
14099a2dd95SBruce Richardson }
14199a2dd95SBruce Richardson
14299a2dd95SBruce Richardson struct rte_event_timer_adapter *
rte_event_timer_adapter_create_ext(const struct rte_event_timer_adapter_conf * conf,rte_event_timer_adapter_port_conf_cb_t conf_cb,void * conf_arg)14399a2dd95SBruce Richardson rte_event_timer_adapter_create_ext(
14499a2dd95SBruce Richardson const struct rte_event_timer_adapter_conf *conf,
14599a2dd95SBruce Richardson rte_event_timer_adapter_port_conf_cb_t conf_cb,
14699a2dd95SBruce Richardson void *conf_arg)
14799a2dd95SBruce Richardson {
14899a2dd95SBruce Richardson uint16_t adapter_id;
14999a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter;
15099a2dd95SBruce Richardson const struct rte_memzone *mz;
15199a2dd95SBruce Richardson char mz_name[DATA_MZ_NAME_MAX_LEN];
15299a2dd95SBruce Richardson int n, ret;
15399a2dd95SBruce Richardson struct rte_eventdev *dev;
15499a2dd95SBruce Richardson
155f3f3a917SPavan Nikhilesh if (adapters == NULL) {
156f3f3a917SPavan Nikhilesh adapters = rte_zmalloc("Eventdev",
157f3f3a917SPavan Nikhilesh sizeof(struct rte_event_timer_adapter) *
158f3f3a917SPavan Nikhilesh RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
159f3f3a917SPavan Nikhilesh RTE_CACHE_LINE_SIZE);
160f3f3a917SPavan Nikhilesh if (adapters == NULL) {
161f3f3a917SPavan Nikhilesh rte_errno = ENOMEM;
162f3f3a917SPavan Nikhilesh return NULL;
163f3f3a917SPavan Nikhilesh }
164f3f3a917SPavan Nikhilesh }
165f3f3a917SPavan Nikhilesh
16699a2dd95SBruce Richardson if (conf == NULL) {
16799a2dd95SBruce Richardson rte_errno = EINVAL;
16899a2dd95SBruce Richardson return NULL;
16999a2dd95SBruce Richardson }
17099a2dd95SBruce Richardson
17199a2dd95SBruce Richardson /* Check eventdev ID */
17299a2dd95SBruce Richardson if (!rte_event_pmd_is_valid_dev(conf->event_dev_id)) {
17399a2dd95SBruce Richardson rte_errno = EINVAL;
17499a2dd95SBruce Richardson return NULL;
17599a2dd95SBruce Richardson }
17699a2dd95SBruce Richardson dev = &rte_eventdevs[conf->event_dev_id];
17799a2dd95SBruce Richardson
17899a2dd95SBruce Richardson adapter_id = conf->timer_adapter_id;
17999a2dd95SBruce Richardson
18099a2dd95SBruce Richardson /* Check that adapter_id is in range */
18199a2dd95SBruce Richardson if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
18299a2dd95SBruce Richardson rte_errno = EINVAL;
18399a2dd95SBruce Richardson return NULL;
18499a2dd95SBruce Richardson }
18599a2dd95SBruce Richardson
18699a2dd95SBruce Richardson /* Check adapter ID not already allocated */
18799a2dd95SBruce Richardson adapter = &adapters[adapter_id];
18899a2dd95SBruce Richardson if (adapter->allocated) {
18999a2dd95SBruce Richardson rte_errno = EEXIST;
19099a2dd95SBruce Richardson return NULL;
19199a2dd95SBruce Richardson }
19299a2dd95SBruce Richardson
19399a2dd95SBruce Richardson /* Create shared data area. */
19499a2dd95SBruce Richardson n = snprintf(mz_name, sizeof(mz_name), DATA_MZ_NAME_FORMAT, adapter_id);
19599a2dd95SBruce Richardson if (n >= (int)sizeof(mz_name)) {
19699a2dd95SBruce Richardson rte_errno = EINVAL;
19799a2dd95SBruce Richardson return NULL;
19899a2dd95SBruce Richardson }
19999a2dd95SBruce Richardson mz = rte_memzone_reserve(mz_name,
20099a2dd95SBruce Richardson sizeof(struct rte_event_timer_adapter_data),
20199a2dd95SBruce Richardson conf->socket_id, 0);
20299a2dd95SBruce Richardson if (mz == NULL)
20399a2dd95SBruce Richardson /* rte_errno set by rte_memzone_reserve */
20499a2dd95SBruce Richardson return NULL;
20599a2dd95SBruce Richardson
20699a2dd95SBruce Richardson adapter->data = mz->addr;
20799a2dd95SBruce Richardson memset(adapter->data, 0, sizeof(struct rte_event_timer_adapter_data));
20899a2dd95SBruce Richardson
20999a2dd95SBruce Richardson adapter->data->mz = mz;
21099a2dd95SBruce Richardson adapter->data->event_dev_id = conf->event_dev_id;
21199a2dd95SBruce Richardson adapter->data->id = adapter_id;
21299a2dd95SBruce Richardson adapter->data->socket_id = conf->socket_id;
21399a2dd95SBruce Richardson adapter->data->conf = *conf; /* copy conf structure */
21499a2dd95SBruce Richardson
21599a2dd95SBruce Richardson /* Query eventdev PMD for timer adapter capabilities and ops */
2163d9d8adfSNaga Harish K S V if (dev->dev_ops->timer_adapter_caps_get) {
21799a2dd95SBruce Richardson ret = dev->dev_ops->timer_adapter_caps_get(dev,
21899a2dd95SBruce Richardson adapter->data->conf.flags,
2193d9d8adfSNaga Harish K S V &adapter->data->caps, &adapter->ops);
22099a2dd95SBruce Richardson if (ret < 0) {
22199a2dd95SBruce Richardson rte_errno = -ret;
22299a2dd95SBruce Richardson goto free_memzone;
22399a2dd95SBruce Richardson }
2243d9d8adfSNaga Harish K S V }
22599a2dd95SBruce Richardson
22699a2dd95SBruce Richardson if (!(adapter->data->caps &
22799a2dd95SBruce Richardson RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
22899a2dd95SBruce Richardson FUNC_PTR_OR_NULL_RET_WITH_ERRNO(conf_cb, EINVAL);
22999a2dd95SBruce Richardson ret = conf_cb(adapter->data->id, adapter->data->event_dev_id,
23099a2dd95SBruce Richardson &adapter->data->event_port_id, conf_arg);
23199a2dd95SBruce Richardson if (ret < 0) {
23299a2dd95SBruce Richardson rte_errno = -ret;
23399a2dd95SBruce Richardson goto free_memzone;
23499a2dd95SBruce Richardson }
23599a2dd95SBruce Richardson }
23699a2dd95SBruce Richardson
23799a2dd95SBruce Richardson /* If eventdev PMD did not provide ops, use default software
23899a2dd95SBruce Richardson * implementation.
23999a2dd95SBruce Richardson */
24099a2dd95SBruce Richardson if (adapter->ops == NULL)
24199a2dd95SBruce Richardson adapter->ops = &swtim_ops;
24299a2dd95SBruce Richardson
24399a2dd95SBruce Richardson /* Allow driver to do some setup */
24499a2dd95SBruce Richardson FUNC_PTR_OR_NULL_RET_WITH_ERRNO(adapter->ops->init, ENOTSUP);
24599a2dd95SBruce Richardson ret = adapter->ops->init(adapter);
24699a2dd95SBruce Richardson if (ret < 0) {
24799a2dd95SBruce Richardson rte_errno = -ret;
24899a2dd95SBruce Richardson goto free_memzone;
24999a2dd95SBruce Richardson }
25099a2dd95SBruce Richardson
25199a2dd95SBruce Richardson /* Set fast-path function pointers */
25299a2dd95SBruce Richardson adapter->arm_burst = adapter->ops->arm_burst;
25399a2dd95SBruce Richardson adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
25499a2dd95SBruce Richardson adapter->cancel_burst = adapter->ops->cancel_burst;
25599a2dd95SBruce Richardson
25699a2dd95SBruce Richardson adapter->allocated = 1;
25799a2dd95SBruce Richardson
25899a2dd95SBruce Richardson rte_eventdev_trace_timer_adapter_create(adapter_id, adapter, conf,
25999a2dd95SBruce Richardson conf_cb);
26099a2dd95SBruce Richardson return adapter;
26199a2dd95SBruce Richardson
26299a2dd95SBruce Richardson free_memzone:
26399a2dd95SBruce Richardson rte_memzone_free(adapter->data->mz);
26499a2dd95SBruce Richardson return NULL;
26599a2dd95SBruce Richardson }
26699a2dd95SBruce Richardson
26799a2dd95SBruce Richardson int
rte_event_timer_adapter_get_info(const struct rte_event_timer_adapter * adapter,struct rte_event_timer_adapter_info * adapter_info)26899a2dd95SBruce Richardson rte_event_timer_adapter_get_info(const struct rte_event_timer_adapter *adapter,
26999a2dd95SBruce Richardson struct rte_event_timer_adapter_info *adapter_info)
27099a2dd95SBruce Richardson {
27199a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
27299a2dd95SBruce Richardson
27399a2dd95SBruce Richardson if (adapter->ops->get_info)
27499a2dd95SBruce Richardson /* let driver set values it knows */
27599a2dd95SBruce Richardson adapter->ops->get_info(adapter, adapter_info);
27699a2dd95SBruce Richardson
27799a2dd95SBruce Richardson /* Set common values */
27899a2dd95SBruce Richardson adapter_info->conf = adapter->data->conf;
27999a2dd95SBruce Richardson adapter_info->event_dev_port_id = adapter->data->event_port_id;
28099a2dd95SBruce Richardson adapter_info->caps = adapter->data->caps;
28199a2dd95SBruce Richardson
2827f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_adapter_get_info(adapter, adapter_info);
2837f2d9df6SAmit Prakash Shukla
28499a2dd95SBruce Richardson return 0;
28599a2dd95SBruce Richardson }
28699a2dd95SBruce Richardson
28799a2dd95SBruce Richardson int
rte_event_timer_adapter_start(const struct rte_event_timer_adapter * adapter)28899a2dd95SBruce Richardson rte_event_timer_adapter_start(const struct rte_event_timer_adapter *adapter)
28999a2dd95SBruce Richardson {
29099a2dd95SBruce Richardson int ret;
29199a2dd95SBruce Richardson
29299a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
29399a2dd95SBruce Richardson FUNC_PTR_OR_ERR_RET(adapter->ops->start, -EINVAL);
29499a2dd95SBruce Richardson
29599a2dd95SBruce Richardson if (adapter->data->started) {
29699a2dd95SBruce Richardson EVTIM_LOG_ERR("event timer adapter %"PRIu8" already started",
29799a2dd95SBruce Richardson adapter->data->id);
29899a2dd95SBruce Richardson return -EALREADY;
29999a2dd95SBruce Richardson }
30099a2dd95SBruce Richardson
30199a2dd95SBruce Richardson ret = adapter->ops->start(adapter);
30299a2dd95SBruce Richardson if (ret < 0)
30399a2dd95SBruce Richardson return ret;
30499a2dd95SBruce Richardson
30599a2dd95SBruce Richardson adapter->data->started = 1;
30699a2dd95SBruce Richardson rte_eventdev_trace_timer_adapter_start(adapter);
30799a2dd95SBruce Richardson return 0;
30899a2dd95SBruce Richardson }
30999a2dd95SBruce Richardson
31099a2dd95SBruce Richardson int
rte_event_timer_adapter_stop(const struct rte_event_timer_adapter * adapter)31199a2dd95SBruce Richardson rte_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter)
31299a2dd95SBruce Richardson {
31399a2dd95SBruce Richardson int ret;
31499a2dd95SBruce Richardson
31599a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
31699a2dd95SBruce Richardson FUNC_PTR_OR_ERR_RET(adapter->ops->stop, -EINVAL);
31799a2dd95SBruce Richardson
31899a2dd95SBruce Richardson if (adapter->data->started == 0) {
31999a2dd95SBruce Richardson EVTIM_LOG_ERR("event timer adapter %"PRIu8" already stopped",
32099a2dd95SBruce Richardson adapter->data->id);
32199a2dd95SBruce Richardson return 0;
32299a2dd95SBruce Richardson }
32399a2dd95SBruce Richardson
32499a2dd95SBruce Richardson ret = adapter->ops->stop(adapter);
32599a2dd95SBruce Richardson if (ret < 0)
32699a2dd95SBruce Richardson return ret;
32799a2dd95SBruce Richardson
32899a2dd95SBruce Richardson adapter->data->started = 0;
32999a2dd95SBruce Richardson rte_eventdev_trace_timer_adapter_stop(adapter);
33099a2dd95SBruce Richardson return 0;
33199a2dd95SBruce Richardson }
33299a2dd95SBruce Richardson
33399a2dd95SBruce Richardson struct rte_event_timer_adapter *
rte_event_timer_adapter_lookup(uint16_t adapter_id)33499a2dd95SBruce Richardson rte_event_timer_adapter_lookup(uint16_t adapter_id)
33599a2dd95SBruce Richardson {
33699a2dd95SBruce Richardson char name[DATA_MZ_NAME_MAX_LEN];
33799a2dd95SBruce Richardson const struct rte_memzone *mz;
33899a2dd95SBruce Richardson struct rte_event_timer_adapter_data *data;
33999a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter;
34099a2dd95SBruce Richardson int ret;
34199a2dd95SBruce Richardson struct rte_eventdev *dev;
34299a2dd95SBruce Richardson
343f3f3a917SPavan Nikhilesh if (adapters == NULL) {
344f3f3a917SPavan Nikhilesh adapters = rte_zmalloc("Eventdev",
345f3f3a917SPavan Nikhilesh sizeof(struct rte_event_timer_adapter) *
346f3f3a917SPavan Nikhilesh RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
347f3f3a917SPavan Nikhilesh RTE_CACHE_LINE_SIZE);
348f3f3a917SPavan Nikhilesh if (adapters == NULL) {
349f3f3a917SPavan Nikhilesh rte_errno = ENOMEM;
350f3f3a917SPavan Nikhilesh return NULL;
351f3f3a917SPavan Nikhilesh }
352f3f3a917SPavan Nikhilesh }
353f3f3a917SPavan Nikhilesh
35499a2dd95SBruce Richardson if (adapters[adapter_id].allocated)
35599a2dd95SBruce Richardson return &adapters[adapter_id]; /* Adapter is already loaded */
35699a2dd95SBruce Richardson
35799a2dd95SBruce Richardson snprintf(name, DATA_MZ_NAME_MAX_LEN, DATA_MZ_NAME_FORMAT, adapter_id);
35899a2dd95SBruce Richardson mz = rte_memzone_lookup(name);
35999a2dd95SBruce Richardson if (mz == NULL) {
36099a2dd95SBruce Richardson rte_errno = ENOENT;
36199a2dd95SBruce Richardson return NULL;
36299a2dd95SBruce Richardson }
36399a2dd95SBruce Richardson
36499a2dd95SBruce Richardson data = mz->addr;
36599a2dd95SBruce Richardson
36699a2dd95SBruce Richardson adapter = &adapters[data->id];
36799a2dd95SBruce Richardson adapter->data = data;
36899a2dd95SBruce Richardson
36999a2dd95SBruce Richardson dev = &rte_eventdevs[adapter->data->event_dev_id];
37099a2dd95SBruce Richardson
37199a2dd95SBruce Richardson /* Query eventdev PMD for timer adapter capabilities and ops */
3723d9d8adfSNaga Harish K S V if (dev->dev_ops->timer_adapter_caps_get) {
37399a2dd95SBruce Richardson ret = dev->dev_ops->timer_adapter_caps_get(dev,
37499a2dd95SBruce Richardson adapter->data->conf.flags,
3753d9d8adfSNaga Harish K S V &adapter->data->caps, &adapter->ops);
37699a2dd95SBruce Richardson if (ret < 0) {
37799a2dd95SBruce Richardson rte_errno = EINVAL;
37899a2dd95SBruce Richardson return NULL;
37999a2dd95SBruce Richardson }
3803d9d8adfSNaga Harish K S V }
38199a2dd95SBruce Richardson
38299a2dd95SBruce Richardson /* If eventdev PMD did not provide ops, use default software
38399a2dd95SBruce Richardson * implementation.
38499a2dd95SBruce Richardson */
38599a2dd95SBruce Richardson if (adapter->ops == NULL)
38699a2dd95SBruce Richardson adapter->ops = &swtim_ops;
38799a2dd95SBruce Richardson
38899a2dd95SBruce Richardson /* Set fast-path function pointers */
38999a2dd95SBruce Richardson adapter->arm_burst = adapter->ops->arm_burst;
39099a2dd95SBruce Richardson adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
39199a2dd95SBruce Richardson adapter->cancel_burst = adapter->ops->cancel_burst;
39299a2dd95SBruce Richardson
39399a2dd95SBruce Richardson adapter->allocated = 1;
39499a2dd95SBruce Richardson
3957f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_adapter_lookup(adapter_id, adapter);
3967f2d9df6SAmit Prakash Shukla
39799a2dd95SBruce Richardson return adapter;
39899a2dd95SBruce Richardson }
39999a2dd95SBruce Richardson
40099a2dd95SBruce Richardson int
rte_event_timer_adapter_free(struct rte_event_timer_adapter * adapter)40199a2dd95SBruce Richardson rte_event_timer_adapter_free(struct rte_event_timer_adapter *adapter)
40299a2dd95SBruce Richardson {
403f3f3a917SPavan Nikhilesh int i, ret;
40499a2dd95SBruce Richardson
40599a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
40699a2dd95SBruce Richardson FUNC_PTR_OR_ERR_RET(adapter->ops->uninit, -EINVAL);
40799a2dd95SBruce Richardson
40899a2dd95SBruce Richardson if (adapter->data->started == 1) {
40999a2dd95SBruce Richardson EVTIM_LOG_ERR("event timer adapter %"PRIu8" must be stopped "
41099a2dd95SBruce Richardson "before freeing", adapter->data->id);
41199a2dd95SBruce Richardson return -EBUSY;
41299a2dd95SBruce Richardson }
41399a2dd95SBruce Richardson
41499a2dd95SBruce Richardson /* free impl priv data */
41599a2dd95SBruce Richardson ret = adapter->ops->uninit(adapter);
41699a2dd95SBruce Richardson if (ret < 0)
41799a2dd95SBruce Richardson return ret;
41899a2dd95SBruce Richardson
41999a2dd95SBruce Richardson /* free shared data area */
42099a2dd95SBruce Richardson ret = rte_memzone_free(adapter->data->mz);
42199a2dd95SBruce Richardson if (ret < 0)
42299a2dd95SBruce Richardson return ret;
42399a2dd95SBruce Richardson
42499a2dd95SBruce Richardson adapter->data = NULL;
42599a2dd95SBruce Richardson adapter->allocated = 0;
42699a2dd95SBruce Richardson
427f3f3a917SPavan Nikhilesh ret = 0;
428f3f3a917SPavan Nikhilesh for (i = 0; i < RTE_EVENT_TIMER_ADAPTER_NUM_MAX; i++)
429f3f3a917SPavan Nikhilesh if (adapters[i].allocated)
430f3f3a917SPavan Nikhilesh ret = adapters[i].allocated;
431f3f3a917SPavan Nikhilesh
432f3f3a917SPavan Nikhilesh if (!ret) {
433f3f3a917SPavan Nikhilesh rte_free(adapters);
434f3f3a917SPavan Nikhilesh adapters = NULL;
435f3f3a917SPavan Nikhilesh }
436f3f3a917SPavan Nikhilesh
43799a2dd95SBruce Richardson rte_eventdev_trace_timer_adapter_free(adapter);
43899a2dd95SBruce Richardson return 0;
43999a2dd95SBruce Richardson }
44099a2dd95SBruce Richardson
44199a2dd95SBruce Richardson int
rte_event_timer_adapter_service_id_get(struct rte_event_timer_adapter * adapter,uint32_t * service_id)44299a2dd95SBruce Richardson rte_event_timer_adapter_service_id_get(struct rte_event_timer_adapter *adapter,
44399a2dd95SBruce Richardson uint32_t *service_id)
44499a2dd95SBruce Richardson {
44599a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
44699a2dd95SBruce Richardson
4477f2d9df6SAmit Prakash Shukla if (service_id == NULL)
4487f2d9df6SAmit Prakash Shukla return -EINVAL;
4497f2d9df6SAmit Prakash Shukla
45099a2dd95SBruce Richardson if (adapter->data->service_inited && service_id != NULL)
45199a2dd95SBruce Richardson *service_id = adapter->data->service_id;
45299a2dd95SBruce Richardson
4537f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_adapter_service_id_get(adapter, *service_id);
4547f2d9df6SAmit Prakash Shukla
45599a2dd95SBruce Richardson return adapter->data->service_inited ? 0 : -ESRCH;
45699a2dd95SBruce Richardson }
45799a2dd95SBruce Richardson
45899a2dd95SBruce Richardson int
rte_event_timer_adapter_stats_get(struct rte_event_timer_adapter * adapter,struct rte_event_timer_adapter_stats * stats)45999a2dd95SBruce Richardson rte_event_timer_adapter_stats_get(struct rte_event_timer_adapter *adapter,
46099a2dd95SBruce Richardson struct rte_event_timer_adapter_stats *stats)
46199a2dd95SBruce Richardson {
4627f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_adapter_stats_get(adapter, stats);
4637f2d9df6SAmit Prakash Shukla
46499a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
46599a2dd95SBruce Richardson FUNC_PTR_OR_ERR_RET(adapter->ops->stats_get, -EINVAL);
46699a2dd95SBruce Richardson if (stats == NULL)
46799a2dd95SBruce Richardson return -EINVAL;
46899a2dd95SBruce Richardson
46999a2dd95SBruce Richardson return adapter->ops->stats_get(adapter, stats);
47099a2dd95SBruce Richardson }
47199a2dd95SBruce Richardson
47299a2dd95SBruce Richardson int
rte_event_timer_adapter_stats_reset(struct rte_event_timer_adapter * adapter)47399a2dd95SBruce Richardson rte_event_timer_adapter_stats_reset(struct rte_event_timer_adapter *adapter)
47499a2dd95SBruce Richardson {
4757f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_adapter_stats_reset(adapter);
4767f2d9df6SAmit Prakash Shukla
47799a2dd95SBruce Richardson ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
47899a2dd95SBruce Richardson FUNC_PTR_OR_ERR_RET(adapter->ops->stats_reset, -EINVAL);
47999a2dd95SBruce Richardson return adapter->ops->stats_reset(adapter);
48099a2dd95SBruce Richardson }
48199a2dd95SBruce Richardson
4820727ff34SErik Gabriel Carrillo int
rte_event_timer_remaining_ticks_get(const struct rte_event_timer_adapter * adapter,const struct rte_event_timer * evtim,uint64_t * ticks_remaining)4830727ff34SErik Gabriel Carrillo rte_event_timer_remaining_ticks_get(
4840727ff34SErik Gabriel Carrillo const struct rte_event_timer_adapter *adapter,
4850727ff34SErik Gabriel Carrillo const struct rte_event_timer *evtim,
4860727ff34SErik Gabriel Carrillo uint64_t *ticks_remaining)
4870727ff34SErik Gabriel Carrillo {
4887f2d9df6SAmit Prakash Shukla rte_eventdev_trace_timer_remaining_ticks_get(adapter, evtim, ticks_remaining);
4897f2d9df6SAmit Prakash Shukla
4900727ff34SErik Gabriel Carrillo ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
4910727ff34SErik Gabriel Carrillo FUNC_PTR_OR_ERR_RET(adapter->ops->remaining_ticks_get, -ENOTSUP);
4920727ff34SErik Gabriel Carrillo
4930727ff34SErik Gabriel Carrillo if (ticks_remaining == NULL)
4940727ff34SErik Gabriel Carrillo return -EINVAL;
4950727ff34SErik Gabriel Carrillo
4960727ff34SErik Gabriel Carrillo return adapter->ops->remaining_ticks_get(adapter, evtim,
4970727ff34SErik Gabriel Carrillo ticks_remaining);
4980727ff34SErik Gabriel Carrillo }
4990727ff34SErik Gabriel Carrillo
50099a2dd95SBruce Richardson /*
50199a2dd95SBruce Richardson * Software event timer adapter buffer helper functions
50299a2dd95SBruce Richardson */
50399a2dd95SBruce Richardson
50499a2dd95SBruce Richardson #define NSECPERSEC 1E9
50599a2dd95SBruce Richardson
50699a2dd95SBruce Richardson /* Optimizations used to index into the buffer require that the buffer size
50799a2dd95SBruce Richardson * be a power of 2.
50899a2dd95SBruce Richardson */
50999a2dd95SBruce Richardson #define EVENT_BUFFER_SZ 4096
51099a2dd95SBruce Richardson #define EVENT_BUFFER_BATCHSZ 32
51199a2dd95SBruce Richardson #define EVENT_BUFFER_MASK (EVENT_BUFFER_SZ - 1)
51299a2dd95SBruce Richardson
51399a2dd95SBruce Richardson #define EXP_TIM_BUF_SZ 128
51499a2dd95SBruce Richardson
515*c6552d9aSTyler Retzlaff struct __rte_cache_aligned event_buffer {
51699a2dd95SBruce Richardson size_t head;
51799a2dd95SBruce Richardson size_t tail;
51899a2dd95SBruce Richardson struct rte_event events[EVENT_BUFFER_SZ];
519*c6552d9aSTyler Retzlaff };
52099a2dd95SBruce Richardson
52199a2dd95SBruce Richardson static inline bool
event_buffer_full(struct event_buffer * bufp)52299a2dd95SBruce Richardson event_buffer_full(struct event_buffer *bufp)
52399a2dd95SBruce Richardson {
52499a2dd95SBruce Richardson return (bufp->head - bufp->tail) == EVENT_BUFFER_SZ;
52599a2dd95SBruce Richardson }
52699a2dd95SBruce Richardson
52799a2dd95SBruce Richardson static inline bool
event_buffer_batch_ready(struct event_buffer * bufp)52899a2dd95SBruce Richardson event_buffer_batch_ready(struct event_buffer *bufp)
52999a2dd95SBruce Richardson {
53099a2dd95SBruce Richardson return (bufp->head - bufp->tail) >= EVENT_BUFFER_BATCHSZ;
53199a2dd95SBruce Richardson }
53299a2dd95SBruce Richardson
53399a2dd95SBruce Richardson static void
event_buffer_init(struct event_buffer * bufp)53499a2dd95SBruce Richardson event_buffer_init(struct event_buffer *bufp)
53599a2dd95SBruce Richardson {
53699a2dd95SBruce Richardson bufp->head = bufp->tail = 0;
53799a2dd95SBruce Richardson memset(&bufp->events, 0, sizeof(struct rte_event) * EVENT_BUFFER_SZ);
53899a2dd95SBruce Richardson }
53999a2dd95SBruce Richardson
54099a2dd95SBruce Richardson static int
event_buffer_add(struct event_buffer * bufp,struct rte_event * eventp)54199a2dd95SBruce Richardson event_buffer_add(struct event_buffer *bufp, struct rte_event *eventp)
54299a2dd95SBruce Richardson {
54399a2dd95SBruce Richardson size_t head_idx;
54499a2dd95SBruce Richardson struct rte_event *buf_eventp;
54599a2dd95SBruce Richardson
54699a2dd95SBruce Richardson if (event_buffer_full(bufp))
54799a2dd95SBruce Richardson return -1;
54899a2dd95SBruce Richardson
54999a2dd95SBruce Richardson /* Instead of modulus, bitwise AND with mask to get head_idx. */
55099a2dd95SBruce Richardson head_idx = bufp->head & EVENT_BUFFER_MASK;
55199a2dd95SBruce Richardson buf_eventp = &bufp->events[head_idx];
55299a2dd95SBruce Richardson rte_memcpy(buf_eventp, eventp, sizeof(struct rte_event));
55399a2dd95SBruce Richardson
55499a2dd95SBruce Richardson /* Wrap automatically when overflow occurs. */
55599a2dd95SBruce Richardson bufp->head++;
55699a2dd95SBruce Richardson
55799a2dd95SBruce Richardson return 0;
55899a2dd95SBruce Richardson }
55999a2dd95SBruce Richardson
56099a2dd95SBruce Richardson static void
event_buffer_flush(struct event_buffer * bufp,uint8_t dev_id,uint8_t port_id,uint16_t * nb_events_flushed,uint16_t * nb_events_inv)56199a2dd95SBruce Richardson event_buffer_flush(struct event_buffer *bufp, uint8_t dev_id, uint8_t port_id,
56299a2dd95SBruce Richardson uint16_t *nb_events_flushed,
56399a2dd95SBruce Richardson uint16_t *nb_events_inv)
56499a2dd95SBruce Richardson {
56599a2dd95SBruce Richardson struct rte_event *events = bufp->events;
56699a2dd95SBruce Richardson size_t head_idx, tail_idx;
56799a2dd95SBruce Richardson uint16_t n = 0;
56899a2dd95SBruce Richardson
56999a2dd95SBruce Richardson /* Instead of modulus, bitwise AND with mask to get index. */
57099a2dd95SBruce Richardson head_idx = bufp->head & EVENT_BUFFER_MASK;
57199a2dd95SBruce Richardson tail_idx = bufp->tail & EVENT_BUFFER_MASK;
57299a2dd95SBruce Richardson
57399a2dd95SBruce Richardson RTE_ASSERT(head_idx < EVENT_BUFFER_SZ && tail_idx < EVENT_BUFFER_SZ);
57499a2dd95SBruce Richardson
5754a6672c2SStephen Hemminger /* Determine the largest contiguous run we can attempt to enqueue to the
57699a2dd95SBruce Richardson * event device.
57799a2dd95SBruce Richardson */
57899a2dd95SBruce Richardson if (head_idx > tail_idx)
57999a2dd95SBruce Richardson n = head_idx - tail_idx;
58099a2dd95SBruce Richardson else if (head_idx < tail_idx)
58199a2dd95SBruce Richardson n = EVENT_BUFFER_SZ - tail_idx;
58299a2dd95SBruce Richardson else if (event_buffer_full(bufp))
58399a2dd95SBruce Richardson n = EVENT_BUFFER_SZ - tail_idx;
58499a2dd95SBruce Richardson else {
58599a2dd95SBruce Richardson *nb_events_flushed = 0;
58699a2dd95SBruce Richardson return;
58799a2dd95SBruce Richardson }
58899a2dd95SBruce Richardson
58999a2dd95SBruce Richardson n = RTE_MIN(EVENT_BUFFER_BATCHSZ, n);
59099a2dd95SBruce Richardson *nb_events_inv = 0;
59199a2dd95SBruce Richardson
59299a2dd95SBruce Richardson *nb_events_flushed = rte_event_enqueue_burst(dev_id, port_id,
59399a2dd95SBruce Richardson &events[tail_idx], n);
59499a2dd95SBruce Richardson if (*nb_events_flushed != n) {
59599a2dd95SBruce Richardson if (rte_errno == EINVAL) {
59699a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to enqueue invalid event - "
59799a2dd95SBruce Richardson "dropping it");
59899a2dd95SBruce Richardson (*nb_events_inv)++;
59999a2dd95SBruce Richardson } else if (rte_errno == ENOSPC)
60099a2dd95SBruce Richardson rte_pause();
60199a2dd95SBruce Richardson }
60299a2dd95SBruce Richardson
60399a2dd95SBruce Richardson if (*nb_events_flushed > 0)
60499a2dd95SBruce Richardson EVTIM_BUF_LOG_DBG("enqueued %"PRIu16" timer events to event "
60599a2dd95SBruce Richardson "device", *nb_events_flushed);
60699a2dd95SBruce Richardson
60799a2dd95SBruce Richardson bufp->tail = bufp->tail + *nb_events_flushed + *nb_events_inv;
60899a2dd95SBruce Richardson }
60999a2dd95SBruce Richardson
61099a2dd95SBruce Richardson /*
61199a2dd95SBruce Richardson * Software event timer adapter implementation
61299a2dd95SBruce Richardson */
61399a2dd95SBruce Richardson struct swtim {
61499a2dd95SBruce Richardson /* Identifier of service executing timer management logic. */
61599a2dd95SBruce Richardson uint32_t service_id;
61699a2dd95SBruce Richardson /* The cycle count at which the adapter should next tick */
61799a2dd95SBruce Richardson uint64_t next_tick_cycles;
61899a2dd95SBruce Richardson /* The tick resolution used by adapter instance. May have been
61999a2dd95SBruce Richardson * adjusted from what user requested
62099a2dd95SBruce Richardson */
62199a2dd95SBruce Richardson uint64_t timer_tick_ns;
62299a2dd95SBruce Richardson /* Maximum timeout in nanoseconds allowed by adapter instance. */
62399a2dd95SBruce Richardson uint64_t max_tmo_ns;
62499a2dd95SBruce Richardson /* Buffered timer expiry events to be enqueued to an event device. */
62599a2dd95SBruce Richardson struct event_buffer buffer;
62699a2dd95SBruce Richardson /* Statistics */
62799a2dd95SBruce Richardson struct rte_event_timer_adapter_stats stats;
62899a2dd95SBruce Richardson /* Mempool of timer objects */
62999a2dd95SBruce Richardson struct rte_mempool *tim_pool;
63099a2dd95SBruce Richardson /* Back pointer for convenience */
63199a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter;
63299a2dd95SBruce Richardson /* Identifier of timer data instance */
63399a2dd95SBruce Richardson uint32_t timer_data_id;
63499a2dd95SBruce Richardson /* Track which cores have actually armed a timer */
635e9fd1ebfSTyler Retzlaff alignas(RTE_CACHE_LINE_SIZE) struct {
636253de9a8STyler Retzlaff RTE_ATOMIC(uint16_t) v;
637e9fd1ebfSTyler Retzlaff } in_use[RTE_MAX_LCORE];
63899a2dd95SBruce Richardson /* Track which cores' timer lists should be polled */
639253de9a8STyler Retzlaff RTE_ATOMIC(unsigned int) poll_lcores[RTE_MAX_LCORE];
64099a2dd95SBruce Richardson /* The number of lists that should be polled */
641253de9a8STyler Retzlaff RTE_ATOMIC(int) n_poll_lcores;
64299a2dd95SBruce Richardson /* Timers which have expired and can be returned to a mempool */
64399a2dd95SBruce Richardson struct rte_timer *expired_timers[EXP_TIM_BUF_SZ];
64499a2dd95SBruce Richardson /* The number of timers that can be returned to a mempool */
64599a2dd95SBruce Richardson size_t n_expired_timers;
64699a2dd95SBruce Richardson };
64799a2dd95SBruce Richardson
64899a2dd95SBruce Richardson static inline struct swtim *
swtim_pmd_priv(const struct rte_event_timer_adapter * adapter)64999a2dd95SBruce Richardson swtim_pmd_priv(const struct rte_event_timer_adapter *adapter)
65099a2dd95SBruce Richardson {
65199a2dd95SBruce Richardson return adapter->data->adapter_priv;
65299a2dd95SBruce Richardson }
65399a2dd95SBruce Richardson
65499a2dd95SBruce Richardson static void
swtim_callback(struct rte_timer * tim)65599a2dd95SBruce Richardson swtim_callback(struct rte_timer *tim)
65699a2dd95SBruce Richardson {
65799a2dd95SBruce Richardson struct rte_event_timer *evtim = tim->arg;
65899a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter;
65999a2dd95SBruce Richardson unsigned int lcore = rte_lcore_id();
66099a2dd95SBruce Richardson struct swtim *sw;
66199a2dd95SBruce Richardson uint16_t nb_evs_flushed = 0;
66299a2dd95SBruce Richardson uint16_t nb_evs_invalid = 0;
66399a2dd95SBruce Richardson uint64_t opaque;
66499a2dd95SBruce Richardson int ret;
66599a2dd95SBruce Richardson int n_lcores;
6663d9d8adfSNaga Harish K S V enum rte_timer_type type;
66799a2dd95SBruce Richardson
66899a2dd95SBruce Richardson opaque = evtim->impl_opaque[1];
66999a2dd95SBruce Richardson adapter = (struct rte_event_timer_adapter *)(uintptr_t)opaque;
67099a2dd95SBruce Richardson sw = swtim_pmd_priv(adapter);
6713d9d8adfSNaga Harish K S V type = get_timer_type(adapter);
67299a2dd95SBruce Richardson
67399a2dd95SBruce Richardson if (unlikely(sw->in_use[lcore].v == 0)) {
67499a2dd95SBruce Richardson sw->in_use[lcore].v = 1;
675253de9a8STyler Retzlaff n_lcores = rte_atomic_fetch_add_explicit(&sw->n_poll_lcores, 1,
676253de9a8STyler Retzlaff rte_memory_order_relaxed);
677253de9a8STyler Retzlaff rte_atomic_store_explicit(&sw->poll_lcores[n_lcores], lcore,
678253de9a8STyler Retzlaff rte_memory_order_relaxed);
67999a2dd95SBruce Richardson }
6803d9d8adfSNaga Harish K S V
6813d9d8adfSNaga Harish K S V ret = event_buffer_add(&sw->buffer, &evtim->ev);
6823d9d8adfSNaga Harish K S V if (ret < 0) {
6833d9d8adfSNaga Harish K S V if (type == SINGLE) {
6843d9d8adfSNaga Harish K S V /* If event buffer is full, put timer back in list with
6853d9d8adfSNaga Harish K S V * immediate expiry value, so that we process it again
6863d9d8adfSNaga Harish K S V * on the next iteration.
6873d9d8adfSNaga Harish K S V */
6883d9d8adfSNaga Harish K S V ret = rte_timer_alt_reset(sw->timer_data_id, tim, 0,
6893d9d8adfSNaga Harish K S V SINGLE, lcore, NULL, evtim);
6903d9d8adfSNaga Harish K S V if (ret < 0) {
6913d9d8adfSNaga Harish K S V EVTIM_LOG_DBG("event buffer full, failed to "
6923d9d8adfSNaga Harish K S V "reset timer with immediate "
6933d9d8adfSNaga Harish K S V "expiry value");
6943d9d8adfSNaga Harish K S V } else {
6953d9d8adfSNaga Harish K S V sw->stats.evtim_retry_count++;
6963d9d8adfSNaga Harish K S V EVTIM_LOG_DBG("event buffer full, resetting "
6973d9d8adfSNaga Harish K S V "rte_timer with immediate "
6983d9d8adfSNaga Harish K S V "expiry value");
6993d9d8adfSNaga Harish K S V }
7003d9d8adfSNaga Harish K S V } else {
7013d9d8adfSNaga Harish K S V sw->stats.evtim_drop_count++;
7023d9d8adfSNaga Harish K S V }
7033d9d8adfSNaga Harish K S V
70499a2dd95SBruce Richardson } else {
70599a2dd95SBruce Richardson EVTIM_BUF_LOG_DBG("buffered an event timer expiry event");
70699a2dd95SBruce Richardson
70799a2dd95SBruce Richardson /* Empty the buffer here, if necessary, to free older expired
70899a2dd95SBruce Richardson * timers only
70999a2dd95SBruce Richardson */
71099a2dd95SBruce Richardson if (unlikely(sw->n_expired_timers == EXP_TIM_BUF_SZ)) {
71199a2dd95SBruce Richardson rte_mempool_put_bulk(sw->tim_pool,
71299a2dd95SBruce Richardson (void **)sw->expired_timers,
71399a2dd95SBruce Richardson sw->n_expired_timers);
71499a2dd95SBruce Richardson sw->n_expired_timers = 0;
71599a2dd95SBruce Richardson }
71699a2dd95SBruce Richardson
7173d9d8adfSNaga Harish K S V /* Don't free rte_timer for a periodic event timer until
7183d9d8adfSNaga Harish K S V * it is cancelled
7193d9d8adfSNaga Harish K S V */
7203d9d8adfSNaga Harish K S V if (type == SINGLE)
72199a2dd95SBruce Richardson sw->expired_timers[sw->n_expired_timers++] = tim;
72299a2dd95SBruce Richardson sw->stats.evtim_exp_count++;
72399a2dd95SBruce Richardson
7243d9d8adfSNaga Harish K S V if (type == SINGLE)
725253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtim->state, RTE_EVENT_TIMER_NOT_ARMED,
726253de9a8STyler Retzlaff rte_memory_order_release);
72799a2dd95SBruce Richardson }
72899a2dd95SBruce Richardson
72999a2dd95SBruce Richardson if (event_buffer_batch_ready(&sw->buffer)) {
73099a2dd95SBruce Richardson event_buffer_flush(&sw->buffer,
73199a2dd95SBruce Richardson adapter->data->event_dev_id,
73299a2dd95SBruce Richardson adapter->data->event_port_id,
73399a2dd95SBruce Richardson &nb_evs_flushed,
73499a2dd95SBruce Richardson &nb_evs_invalid);
73599a2dd95SBruce Richardson
73699a2dd95SBruce Richardson sw->stats.ev_enq_count += nb_evs_flushed;
73799a2dd95SBruce Richardson sw->stats.ev_inv_count += nb_evs_invalid;
73899a2dd95SBruce Richardson }
73999a2dd95SBruce Richardson }
74099a2dd95SBruce Richardson
74113aba5f8SErik Gabriel Carrillo static __rte_always_inline int
get_timeout_cycles(struct rte_event_timer * evtim,const struct rte_event_timer_adapter * adapter,uint64_t * timeout_cycles)74299a2dd95SBruce Richardson get_timeout_cycles(struct rte_event_timer *evtim,
74313aba5f8SErik Gabriel Carrillo const struct rte_event_timer_adapter *adapter,
74413aba5f8SErik Gabriel Carrillo uint64_t *timeout_cycles)
74599a2dd95SBruce Richardson {
74613aba5f8SErik Gabriel Carrillo static struct rte_reciprocal_u64 nsecpersec_inverse;
74713aba5f8SErik Gabriel Carrillo static uint64_t timer_hz;
74813aba5f8SErik Gabriel Carrillo uint64_t rem_cycles, secs_cycles = 0;
74913aba5f8SErik Gabriel Carrillo uint64_t secs, timeout_nsecs;
75013aba5f8SErik Gabriel Carrillo uint64_t nsecpersec;
75113aba5f8SErik Gabriel Carrillo struct swtim *sw;
75213aba5f8SErik Gabriel Carrillo
75313aba5f8SErik Gabriel Carrillo sw = swtim_pmd_priv(adapter);
75413aba5f8SErik Gabriel Carrillo nsecpersec = (uint64_t)NSECPERSEC;
75513aba5f8SErik Gabriel Carrillo
75613aba5f8SErik Gabriel Carrillo timeout_nsecs = evtim->timeout_ticks * sw->timer_tick_ns;
75713aba5f8SErik Gabriel Carrillo if (timeout_nsecs > sw->max_tmo_ns)
75813aba5f8SErik Gabriel Carrillo return -1;
75913aba5f8SErik Gabriel Carrillo if (timeout_nsecs < sw->timer_tick_ns)
76013aba5f8SErik Gabriel Carrillo return -2;
76113aba5f8SErik Gabriel Carrillo
76213aba5f8SErik Gabriel Carrillo /* Set these values in the first invocation */
76313aba5f8SErik Gabriel Carrillo if (!timer_hz) {
76413aba5f8SErik Gabriel Carrillo timer_hz = rte_get_timer_hz();
76513aba5f8SErik Gabriel Carrillo nsecpersec_inverse = rte_reciprocal_value_u64(nsecpersec);
76613aba5f8SErik Gabriel Carrillo }
76713aba5f8SErik Gabriel Carrillo
76813aba5f8SErik Gabriel Carrillo /* If timeout_nsecs > nsecpersec, decrease timeout_nsecs by the number
76913aba5f8SErik Gabriel Carrillo * of whole seconds it contains and convert that value to a number
77013aba5f8SErik Gabriel Carrillo * of cycles. This keeps timeout_nsecs in the interval [0..nsecpersec)
77113aba5f8SErik Gabriel Carrillo * in order to avoid overflow when we later multiply by timer_hz.
77213aba5f8SErik Gabriel Carrillo */
77313aba5f8SErik Gabriel Carrillo if (timeout_nsecs > nsecpersec) {
77413aba5f8SErik Gabriel Carrillo secs = rte_reciprocal_divide_u64(timeout_nsecs,
77513aba5f8SErik Gabriel Carrillo &nsecpersec_inverse);
77613aba5f8SErik Gabriel Carrillo secs_cycles = secs * timer_hz;
77713aba5f8SErik Gabriel Carrillo timeout_nsecs -= secs * nsecpersec;
77813aba5f8SErik Gabriel Carrillo }
77913aba5f8SErik Gabriel Carrillo
78013aba5f8SErik Gabriel Carrillo rem_cycles = rte_reciprocal_divide_u64(timeout_nsecs * timer_hz,
78113aba5f8SErik Gabriel Carrillo &nsecpersec_inverse);
78213aba5f8SErik Gabriel Carrillo
78313aba5f8SErik Gabriel Carrillo *timeout_cycles = secs_cycles + rem_cycles;
78413aba5f8SErik Gabriel Carrillo
78513aba5f8SErik Gabriel Carrillo return 0;
78699a2dd95SBruce Richardson }
78799a2dd95SBruce Richardson
78899a2dd95SBruce Richardson /* This function returns true if one or more (adapter) ticks have occurred since
78999a2dd95SBruce Richardson * the last time it was called.
79099a2dd95SBruce Richardson */
79199a2dd95SBruce Richardson static inline bool
swtim_did_tick(struct swtim * sw)79299a2dd95SBruce Richardson swtim_did_tick(struct swtim *sw)
79399a2dd95SBruce Richardson {
79499a2dd95SBruce Richardson uint64_t cycles_per_adapter_tick, start_cycles;
79599a2dd95SBruce Richardson uint64_t *next_tick_cyclesp;
79699a2dd95SBruce Richardson
79799a2dd95SBruce Richardson next_tick_cyclesp = &sw->next_tick_cycles;
79899a2dd95SBruce Richardson cycles_per_adapter_tick = sw->timer_tick_ns *
79999a2dd95SBruce Richardson (rte_get_timer_hz() / NSECPERSEC);
80099a2dd95SBruce Richardson start_cycles = rte_get_timer_cycles();
80199a2dd95SBruce Richardson
80299a2dd95SBruce Richardson /* Note: initially, *next_tick_cyclesp == 0, so the clause below will
80399a2dd95SBruce Richardson * execute, and set things going.
80499a2dd95SBruce Richardson */
80599a2dd95SBruce Richardson
80699a2dd95SBruce Richardson if (start_cycles >= *next_tick_cyclesp) {
80799a2dd95SBruce Richardson /* Snap the current cycle count to the preceding adapter tick
80899a2dd95SBruce Richardson * boundary.
80999a2dd95SBruce Richardson */
81099a2dd95SBruce Richardson start_cycles -= start_cycles % cycles_per_adapter_tick;
81199a2dd95SBruce Richardson *next_tick_cyclesp = start_cycles + cycles_per_adapter_tick;
81299a2dd95SBruce Richardson
81399a2dd95SBruce Richardson return true;
81499a2dd95SBruce Richardson }
81599a2dd95SBruce Richardson
81699a2dd95SBruce Richardson return false;
81799a2dd95SBruce Richardson }
81899a2dd95SBruce Richardson
81999a2dd95SBruce Richardson /* Check that event timer event queue sched type matches destination event queue
82099a2dd95SBruce Richardson * sched type
82199a2dd95SBruce Richardson */
82299a2dd95SBruce Richardson static __rte_always_inline int
check_destination_event_queue(struct rte_event_timer * evtim,const struct rte_event_timer_adapter * adapter)82399a2dd95SBruce Richardson check_destination_event_queue(struct rte_event_timer *evtim,
82499a2dd95SBruce Richardson const struct rte_event_timer_adapter *adapter)
82599a2dd95SBruce Richardson {
82699a2dd95SBruce Richardson int ret;
82799a2dd95SBruce Richardson uint32_t sched_type;
82899a2dd95SBruce Richardson
82999a2dd95SBruce Richardson ret = rte_event_queue_attr_get(adapter->data->event_dev_id,
83099a2dd95SBruce Richardson evtim->ev.queue_id,
83199a2dd95SBruce Richardson RTE_EVENT_QUEUE_ATTR_SCHEDULE_TYPE,
83299a2dd95SBruce Richardson &sched_type);
83399a2dd95SBruce Richardson
83499a2dd95SBruce Richardson if ((ret == 0 && evtim->ev.sched_type == sched_type) ||
83599a2dd95SBruce Richardson ret == -EOVERFLOW)
83699a2dd95SBruce Richardson return 0;
83799a2dd95SBruce Richardson
83899a2dd95SBruce Richardson return -1;
83999a2dd95SBruce Richardson }
84099a2dd95SBruce Richardson
84199a2dd95SBruce Richardson static int
swtim_service_func(void * arg)84299a2dd95SBruce Richardson swtim_service_func(void *arg)
84399a2dd95SBruce Richardson {
84499a2dd95SBruce Richardson struct rte_event_timer_adapter *adapter = arg;
84599a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
84699a2dd95SBruce Richardson uint16_t nb_evs_flushed = 0;
84799a2dd95SBruce Richardson uint16_t nb_evs_invalid = 0;
848ed88c5a5SMattias Rönnblom const uint64_t prior_enq_count = sw->stats.ev_enq_count;
84999a2dd95SBruce Richardson
85099a2dd95SBruce Richardson if (swtim_did_tick(sw)) {
85199a2dd95SBruce Richardson rte_timer_alt_manage(sw->timer_data_id,
852253de9a8STyler Retzlaff (unsigned int *)(uintptr_t)sw->poll_lcores,
85399a2dd95SBruce Richardson sw->n_poll_lcores,
85499a2dd95SBruce Richardson swtim_callback);
85599a2dd95SBruce Richardson
85699a2dd95SBruce Richardson /* Return expired timer objects back to mempool */
85799a2dd95SBruce Richardson rte_mempool_put_bulk(sw->tim_pool, (void **)sw->expired_timers,
85899a2dd95SBruce Richardson sw->n_expired_timers);
85999a2dd95SBruce Richardson sw->n_expired_timers = 0;
86099a2dd95SBruce Richardson
86153b97347SErik Gabriel Carrillo sw->stats.adapter_tick_count++;
86253b97347SErik Gabriel Carrillo }
86353b97347SErik Gabriel Carrillo
86499a2dd95SBruce Richardson event_buffer_flush(&sw->buffer,
86599a2dd95SBruce Richardson adapter->data->event_dev_id,
86699a2dd95SBruce Richardson adapter->data->event_port_id,
86799a2dd95SBruce Richardson &nb_evs_flushed,
86899a2dd95SBruce Richardson &nb_evs_invalid);
86999a2dd95SBruce Richardson
87099a2dd95SBruce Richardson sw->stats.ev_enq_count += nb_evs_flushed;
87199a2dd95SBruce Richardson sw->stats.ev_inv_count += nb_evs_invalid;
87299a2dd95SBruce Richardson
873578402f2SMattias Rönnblom rte_event_maintain(adapter->data->event_dev_id,
874578402f2SMattias Rönnblom adapter->data->event_port_id, 0);
875578402f2SMattias Rönnblom
876ed88c5a5SMattias Rönnblom return prior_enq_count == sw->stats.ev_enq_count ? -EAGAIN : 0;
87799a2dd95SBruce Richardson }
87899a2dd95SBruce Richardson
87999a2dd95SBruce Richardson /* The adapter initialization function rounds the mempool size up to the next
88099a2dd95SBruce Richardson * power of 2, so we can take the difference between that value and what the
88199a2dd95SBruce Richardson * user requested, and use the space for caches. This avoids a scenario where a
88299a2dd95SBruce Richardson * user can't arm the number of timers the adapter was configured with because
88399a2dd95SBruce Richardson * mempool objects have been lost to caches.
88499a2dd95SBruce Richardson *
88599a2dd95SBruce Richardson * nb_actual should always be a power of 2, so we can iterate over the powers
88699a2dd95SBruce Richardson * of 2 to see what the largest cache size we can use is.
88799a2dd95SBruce Richardson */
88899a2dd95SBruce Richardson static int
compute_msg_mempool_cache_size(uint64_t nb_requested,uint64_t nb_actual)88999a2dd95SBruce Richardson compute_msg_mempool_cache_size(uint64_t nb_requested, uint64_t nb_actual)
89099a2dd95SBruce Richardson {
89199a2dd95SBruce Richardson int i;
89299a2dd95SBruce Richardson int size;
89399a2dd95SBruce Richardson int cache_size = 0;
89499a2dd95SBruce Richardson
89599a2dd95SBruce Richardson for (i = 0;; i++) {
89699a2dd95SBruce Richardson size = 1 << i;
89799a2dd95SBruce Richardson
89899a2dd95SBruce Richardson if (RTE_MAX_LCORE * size < (int)(nb_actual - nb_requested) &&
89999a2dd95SBruce Richardson size < RTE_MEMPOOL_CACHE_MAX_SIZE &&
90099a2dd95SBruce Richardson size <= nb_actual / 1.5)
90199a2dd95SBruce Richardson cache_size = size;
90299a2dd95SBruce Richardson else
90399a2dd95SBruce Richardson break;
90499a2dd95SBruce Richardson }
90599a2dd95SBruce Richardson
90699a2dd95SBruce Richardson return cache_size;
90799a2dd95SBruce Richardson }
90899a2dd95SBruce Richardson
90999a2dd95SBruce Richardson static int
swtim_init(struct rte_event_timer_adapter * adapter)91099a2dd95SBruce Richardson swtim_init(struct rte_event_timer_adapter *adapter)
91199a2dd95SBruce Richardson {
91299a2dd95SBruce Richardson int i, ret;
91399a2dd95SBruce Richardson struct swtim *sw;
91499a2dd95SBruce Richardson unsigned int flags;
91599a2dd95SBruce Richardson struct rte_service_spec service;
91699a2dd95SBruce Richardson
91799a2dd95SBruce Richardson /* Allocate storage for private data area */
91899a2dd95SBruce Richardson #define SWTIM_NAMESIZE 32
91999a2dd95SBruce Richardson char swtim_name[SWTIM_NAMESIZE];
92099a2dd95SBruce Richardson snprintf(swtim_name, SWTIM_NAMESIZE, "swtim_%"PRIu8,
92199a2dd95SBruce Richardson adapter->data->id);
92299a2dd95SBruce Richardson sw = rte_zmalloc_socket(swtim_name, sizeof(*sw), RTE_CACHE_LINE_SIZE,
92399a2dd95SBruce Richardson adapter->data->socket_id);
92499a2dd95SBruce Richardson if (sw == NULL) {
92599a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to allocate space for private data");
92699a2dd95SBruce Richardson rte_errno = ENOMEM;
92799a2dd95SBruce Richardson return -1;
92899a2dd95SBruce Richardson }
92999a2dd95SBruce Richardson
93099a2dd95SBruce Richardson /* Connect storage to adapter instance */
93199a2dd95SBruce Richardson adapter->data->adapter_priv = sw;
93299a2dd95SBruce Richardson sw->adapter = adapter;
93399a2dd95SBruce Richardson
93499a2dd95SBruce Richardson sw->timer_tick_ns = adapter->data->conf.timer_tick_ns;
93599a2dd95SBruce Richardson sw->max_tmo_ns = adapter->data->conf.max_tmo_ns;
93699a2dd95SBruce Richardson
93799a2dd95SBruce Richardson /* Create a timer pool */
93899a2dd95SBruce Richardson char pool_name[SWTIM_NAMESIZE];
93999a2dd95SBruce Richardson snprintf(pool_name, SWTIM_NAMESIZE, "swtim_pool_%"PRIu8,
94099a2dd95SBruce Richardson adapter->data->id);
94199a2dd95SBruce Richardson /* Optimal mempool size is a power of 2 minus one */
94299a2dd95SBruce Richardson uint64_t nb_timers = rte_align64pow2(adapter->data->conf.nb_timers);
94399a2dd95SBruce Richardson int pool_size = nb_timers - 1;
94499a2dd95SBruce Richardson int cache_size = compute_msg_mempool_cache_size(
94599a2dd95SBruce Richardson adapter->data->conf.nb_timers, nb_timers);
94699a2dd95SBruce Richardson flags = 0; /* pool is multi-producer, multi-consumer */
94799a2dd95SBruce Richardson sw->tim_pool = rte_mempool_create(pool_name, pool_size,
94899a2dd95SBruce Richardson sizeof(struct rte_timer), cache_size, 0, NULL, NULL,
94999a2dd95SBruce Richardson NULL, NULL, adapter->data->socket_id, flags);
95099a2dd95SBruce Richardson if (sw->tim_pool == NULL) {
95199a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to create timer object mempool");
95299a2dd95SBruce Richardson rte_errno = ENOMEM;
95399a2dd95SBruce Richardson goto free_alloc;
95499a2dd95SBruce Richardson }
95599a2dd95SBruce Richardson
95699a2dd95SBruce Richardson /* Initialize the variables that track in-use timer lists */
95799a2dd95SBruce Richardson for (i = 0; i < RTE_MAX_LCORE; i++)
95899a2dd95SBruce Richardson sw->in_use[i].v = 0;
95999a2dd95SBruce Richardson
96099a2dd95SBruce Richardson /* Initialize the timer subsystem and allocate timer data instance */
96199a2dd95SBruce Richardson ret = rte_timer_subsystem_init();
96299a2dd95SBruce Richardson if (ret < 0) {
96399a2dd95SBruce Richardson if (ret != -EALREADY) {
96499a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to initialize timer subsystem");
96599a2dd95SBruce Richardson rte_errno = -ret;
96699a2dd95SBruce Richardson goto free_mempool;
96799a2dd95SBruce Richardson }
96899a2dd95SBruce Richardson }
96999a2dd95SBruce Richardson
97099a2dd95SBruce Richardson ret = rte_timer_data_alloc(&sw->timer_data_id);
97199a2dd95SBruce Richardson if (ret < 0) {
97299a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to allocate timer data instance");
97399a2dd95SBruce Richardson rte_errno = -ret;
97499a2dd95SBruce Richardson goto free_mempool;
97599a2dd95SBruce Richardson }
97699a2dd95SBruce Richardson
97799a2dd95SBruce Richardson /* Initialize timer event buffer */
97899a2dd95SBruce Richardson event_buffer_init(&sw->buffer);
97999a2dd95SBruce Richardson
98099a2dd95SBruce Richardson sw->adapter = adapter;
98199a2dd95SBruce Richardson
98299a2dd95SBruce Richardson /* Register a service component to run adapter logic */
98399a2dd95SBruce Richardson memset(&service, 0, sizeof(service));
98499a2dd95SBruce Richardson snprintf(service.name, RTE_SERVICE_NAME_MAX,
98599a2dd95SBruce Richardson "swtim_svc_%"PRIu8, adapter->data->id);
98699a2dd95SBruce Richardson service.socket_id = adapter->data->socket_id;
98799a2dd95SBruce Richardson service.callback = swtim_service_func;
98899a2dd95SBruce Richardson service.callback_userdata = adapter;
98999a2dd95SBruce Richardson service.capabilities &= ~(RTE_SERVICE_CAP_MT_SAFE);
99099a2dd95SBruce Richardson ret = rte_service_component_register(&service, &sw->service_id);
99199a2dd95SBruce Richardson if (ret < 0) {
99299a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to register service %s with id %"PRIu32
99399a2dd95SBruce Richardson ": err = %d", service.name, sw->service_id,
99499a2dd95SBruce Richardson ret);
99599a2dd95SBruce Richardson
99699a2dd95SBruce Richardson rte_errno = ENOSPC;
99799a2dd95SBruce Richardson goto free_mempool;
99899a2dd95SBruce Richardson }
99999a2dd95SBruce Richardson
100099a2dd95SBruce Richardson EVTIM_LOG_DBG("registered service %s with id %"PRIu32, service.name,
100199a2dd95SBruce Richardson sw->service_id);
100299a2dd95SBruce Richardson
100399a2dd95SBruce Richardson adapter->data->service_id = sw->service_id;
100499a2dd95SBruce Richardson adapter->data->service_inited = 1;
100599a2dd95SBruce Richardson
100699a2dd95SBruce Richardson return 0;
100799a2dd95SBruce Richardson free_mempool:
100899a2dd95SBruce Richardson rte_mempool_free(sw->tim_pool);
100999a2dd95SBruce Richardson free_alloc:
101099a2dd95SBruce Richardson rte_free(sw);
101199a2dd95SBruce Richardson return -1;
101299a2dd95SBruce Richardson }
101399a2dd95SBruce Richardson
101499a2dd95SBruce Richardson static void
swtim_free_tim(struct rte_timer * tim,void * arg)101599a2dd95SBruce Richardson swtim_free_tim(struct rte_timer *tim, void *arg)
101699a2dd95SBruce Richardson {
101799a2dd95SBruce Richardson struct swtim *sw = arg;
101899a2dd95SBruce Richardson
101999a2dd95SBruce Richardson rte_mempool_put(sw->tim_pool, tim);
102099a2dd95SBruce Richardson }
102199a2dd95SBruce Richardson
102299a2dd95SBruce Richardson /* Traverse the list of outstanding timers and put them back in the mempool
102399a2dd95SBruce Richardson * before freeing the adapter to avoid leaking the memory.
102499a2dd95SBruce Richardson */
102599a2dd95SBruce Richardson static int
swtim_uninit(struct rte_event_timer_adapter * adapter)102699a2dd95SBruce Richardson swtim_uninit(struct rte_event_timer_adapter *adapter)
102799a2dd95SBruce Richardson {
102899a2dd95SBruce Richardson int ret;
102999a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
103099a2dd95SBruce Richardson
103199a2dd95SBruce Richardson /* Free outstanding timers */
103299a2dd95SBruce Richardson rte_timer_stop_all(sw->timer_data_id,
1033253de9a8STyler Retzlaff (unsigned int *)(uintptr_t)sw->poll_lcores,
103499a2dd95SBruce Richardson sw->n_poll_lcores,
103599a2dd95SBruce Richardson swtim_free_tim,
103699a2dd95SBruce Richardson sw);
103799a2dd95SBruce Richardson
10383d9d8adfSNaga Harish K S V ret = rte_timer_data_dealloc(sw->timer_data_id);
10393d9d8adfSNaga Harish K S V if (ret < 0) {
10403d9d8adfSNaga Harish K S V EVTIM_LOG_ERR("failed to deallocate timer data instance");
10413d9d8adfSNaga Harish K S V return ret;
10423d9d8adfSNaga Harish K S V }
10433d9d8adfSNaga Harish K S V
104499a2dd95SBruce Richardson ret = rte_service_component_unregister(sw->service_id);
104599a2dd95SBruce Richardson if (ret < 0) {
104699a2dd95SBruce Richardson EVTIM_LOG_ERR("failed to unregister service component");
104799a2dd95SBruce Richardson return ret;
104899a2dd95SBruce Richardson }
104999a2dd95SBruce Richardson
105099a2dd95SBruce Richardson rte_mempool_free(sw->tim_pool);
105199a2dd95SBruce Richardson rte_free(sw);
105299a2dd95SBruce Richardson adapter->data->adapter_priv = NULL;
105399a2dd95SBruce Richardson
105499a2dd95SBruce Richardson return 0;
105599a2dd95SBruce Richardson }
105699a2dd95SBruce Richardson
105799a2dd95SBruce Richardson static inline int32_t
get_mapped_count_for_service(uint32_t service_id)105899a2dd95SBruce Richardson get_mapped_count_for_service(uint32_t service_id)
105999a2dd95SBruce Richardson {
106099a2dd95SBruce Richardson int32_t core_count, i, mapped_count = 0;
106199a2dd95SBruce Richardson uint32_t lcore_arr[RTE_MAX_LCORE];
106299a2dd95SBruce Richardson
106399a2dd95SBruce Richardson core_count = rte_service_lcore_list(lcore_arr, RTE_MAX_LCORE);
106499a2dd95SBruce Richardson
106599a2dd95SBruce Richardson for (i = 0; i < core_count; i++)
106699a2dd95SBruce Richardson if (rte_service_map_lcore_get(service_id, lcore_arr[i]) == 1)
106799a2dd95SBruce Richardson mapped_count++;
106899a2dd95SBruce Richardson
106999a2dd95SBruce Richardson return mapped_count;
107099a2dd95SBruce Richardson }
107199a2dd95SBruce Richardson
107299a2dd95SBruce Richardson static int
swtim_start(const struct rte_event_timer_adapter * adapter)107399a2dd95SBruce Richardson swtim_start(const struct rte_event_timer_adapter *adapter)
107499a2dd95SBruce Richardson {
107599a2dd95SBruce Richardson int mapped_count;
107699a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
107799a2dd95SBruce Richardson
107899a2dd95SBruce Richardson /* Mapping the service to more than one service core can introduce
107999a2dd95SBruce Richardson * delays while one thread is waiting to acquire a lock, so only allow
108099a2dd95SBruce Richardson * one core to be mapped to the service.
108199a2dd95SBruce Richardson *
108299a2dd95SBruce Richardson * Note: the service could be modified such that it spreads cores to
108399a2dd95SBruce Richardson * poll over multiple service instances.
108499a2dd95SBruce Richardson */
108599a2dd95SBruce Richardson mapped_count = get_mapped_count_for_service(sw->service_id);
108699a2dd95SBruce Richardson
108799a2dd95SBruce Richardson if (mapped_count != 1)
108899a2dd95SBruce Richardson return mapped_count < 1 ? -ENOENT : -ENOTSUP;
108999a2dd95SBruce Richardson
109099a2dd95SBruce Richardson return rte_service_component_runstate_set(sw->service_id, 1);
109199a2dd95SBruce Richardson }
109299a2dd95SBruce Richardson
109399a2dd95SBruce Richardson static int
swtim_stop(const struct rte_event_timer_adapter * adapter)109499a2dd95SBruce Richardson swtim_stop(const struct rte_event_timer_adapter *adapter)
109599a2dd95SBruce Richardson {
109699a2dd95SBruce Richardson int ret;
109799a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
109899a2dd95SBruce Richardson
109999a2dd95SBruce Richardson ret = rte_service_component_runstate_set(sw->service_id, 0);
110099a2dd95SBruce Richardson if (ret < 0)
110199a2dd95SBruce Richardson return ret;
110299a2dd95SBruce Richardson
110399a2dd95SBruce Richardson /* Wait for the service to complete its final iteration */
110499a2dd95SBruce Richardson while (rte_service_may_be_active(sw->service_id))
110599a2dd95SBruce Richardson rte_pause();
110699a2dd95SBruce Richardson
110799a2dd95SBruce Richardson return 0;
110899a2dd95SBruce Richardson }
110999a2dd95SBruce Richardson
111099a2dd95SBruce Richardson static void
swtim_get_info(const struct rte_event_timer_adapter * adapter,struct rte_event_timer_adapter_info * adapter_info)111199a2dd95SBruce Richardson swtim_get_info(const struct rte_event_timer_adapter *adapter,
111299a2dd95SBruce Richardson struct rte_event_timer_adapter_info *adapter_info)
111399a2dd95SBruce Richardson {
111499a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
111599a2dd95SBruce Richardson adapter_info->min_resolution_ns = sw->timer_tick_ns;
111699a2dd95SBruce Richardson adapter_info->max_tmo_ns = sw->max_tmo_ns;
111799a2dd95SBruce Richardson }
111899a2dd95SBruce Richardson
111999a2dd95SBruce Richardson static int
swtim_stats_get(const struct rte_event_timer_adapter * adapter,struct rte_event_timer_adapter_stats * stats)112099a2dd95SBruce Richardson swtim_stats_get(const struct rte_event_timer_adapter *adapter,
112199a2dd95SBruce Richardson struct rte_event_timer_adapter_stats *stats)
112299a2dd95SBruce Richardson {
112399a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
112499a2dd95SBruce Richardson *stats = sw->stats; /* structure copy */
112599a2dd95SBruce Richardson return 0;
112699a2dd95SBruce Richardson }
112799a2dd95SBruce Richardson
112899a2dd95SBruce Richardson static int
swtim_stats_reset(const struct rte_event_timer_adapter * adapter)112999a2dd95SBruce Richardson swtim_stats_reset(const struct rte_event_timer_adapter *adapter)
113099a2dd95SBruce Richardson {
113199a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
113299a2dd95SBruce Richardson memset(&sw->stats, 0, sizeof(sw->stats));
113399a2dd95SBruce Richardson return 0;
113499a2dd95SBruce Richardson }
113599a2dd95SBruce Richardson
11360727ff34SErik Gabriel Carrillo static int
swtim_remaining_ticks_get(const struct rte_event_timer_adapter * adapter,const struct rte_event_timer * evtim,uint64_t * ticks_remaining)11370727ff34SErik Gabriel Carrillo swtim_remaining_ticks_get(const struct rte_event_timer_adapter *adapter,
11380727ff34SErik Gabriel Carrillo const struct rte_event_timer *evtim,
11390727ff34SErik Gabriel Carrillo uint64_t *ticks_remaining)
11400727ff34SErik Gabriel Carrillo {
11410727ff34SErik Gabriel Carrillo uint64_t nsecs_per_adapter_tick, opaque, cycles_remaining;
11420727ff34SErik Gabriel Carrillo enum rte_event_timer_state n_state;
11430727ff34SErik Gabriel Carrillo double nsecs_per_cycle;
11440727ff34SErik Gabriel Carrillo struct rte_timer *tim;
11450727ff34SErik Gabriel Carrillo uint64_t cur_cycles;
11460727ff34SErik Gabriel Carrillo
11470727ff34SErik Gabriel Carrillo /* Check that timer is armed */
1148253de9a8STyler Retzlaff n_state = rte_atomic_load_explicit(&evtim->state, rte_memory_order_acquire);
11490727ff34SErik Gabriel Carrillo if (n_state != RTE_EVENT_TIMER_ARMED)
11500727ff34SErik Gabriel Carrillo return -EINVAL;
11510727ff34SErik Gabriel Carrillo
11520727ff34SErik Gabriel Carrillo opaque = evtim->impl_opaque[0];
11530727ff34SErik Gabriel Carrillo tim = (struct rte_timer *)(uintptr_t)opaque;
11540727ff34SErik Gabriel Carrillo
11550727ff34SErik Gabriel Carrillo cur_cycles = rte_get_timer_cycles();
11560727ff34SErik Gabriel Carrillo if (cur_cycles > tim->expire) {
11570727ff34SErik Gabriel Carrillo *ticks_remaining = 0;
11580727ff34SErik Gabriel Carrillo return 0;
11590727ff34SErik Gabriel Carrillo }
11600727ff34SErik Gabriel Carrillo
11610727ff34SErik Gabriel Carrillo cycles_remaining = tim->expire - cur_cycles;
11620727ff34SErik Gabriel Carrillo nsecs_per_cycle = (double)NSECPERSEC / rte_get_timer_hz();
11630727ff34SErik Gabriel Carrillo nsecs_per_adapter_tick = adapter->data->conf.timer_tick_ns;
11640727ff34SErik Gabriel Carrillo
11650727ff34SErik Gabriel Carrillo *ticks_remaining = (uint64_t)ceil((cycles_remaining * nsecs_per_cycle) /
11660727ff34SErik Gabriel Carrillo nsecs_per_adapter_tick);
11670727ff34SErik Gabriel Carrillo
11680727ff34SErik Gabriel Carrillo return 0;
11690727ff34SErik Gabriel Carrillo }
11700727ff34SErik Gabriel Carrillo
117199a2dd95SBruce Richardson static uint16_t
__swtim_arm_burst(const struct rte_event_timer_adapter * adapter,struct rte_event_timer ** evtims,uint16_t nb_evtims)117299a2dd95SBruce Richardson __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
117399a2dd95SBruce Richardson struct rte_event_timer **evtims,
117499a2dd95SBruce Richardson uint16_t nb_evtims)
117599a2dd95SBruce Richardson {
117699a2dd95SBruce Richardson int i, ret;
117799a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
117899a2dd95SBruce Richardson uint32_t lcore_id = rte_lcore_id();
117999a2dd95SBruce Richardson struct rte_timer *tim, *tims[nb_evtims];
118099a2dd95SBruce Richardson uint64_t cycles;
118199a2dd95SBruce Richardson int n_lcores;
118299a2dd95SBruce Richardson /* Timer list for this lcore is not in use. */
118399a2dd95SBruce Richardson uint16_t exp_state = 0;
118499a2dd95SBruce Richardson enum rte_event_timer_state n_state;
11853d9d8adfSNaga Harish K S V enum rte_timer_type type = SINGLE;
118699a2dd95SBruce Richardson
118799a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
118899a2dd95SBruce Richardson /* Check that the service is running. */
118999a2dd95SBruce Richardson if (rte_service_runstate_get(adapter->data->service_id) != 1) {
119099a2dd95SBruce Richardson rte_errno = EINVAL;
119199a2dd95SBruce Richardson return 0;
119299a2dd95SBruce Richardson }
119399a2dd95SBruce Richardson #endif
119499a2dd95SBruce Richardson
119599a2dd95SBruce Richardson /* Adjust lcore_id if non-EAL thread. Arbitrarily pick the timer list of
119699a2dd95SBruce Richardson * the highest lcore to insert such timers into
119799a2dd95SBruce Richardson */
119899a2dd95SBruce Richardson if (lcore_id == LCORE_ID_ANY)
119999a2dd95SBruce Richardson lcore_id = RTE_MAX_LCORE - 1;
120099a2dd95SBruce Richardson
120199a2dd95SBruce Richardson /* If this is the first time we're arming an event timer on this lcore,
120299a2dd95SBruce Richardson * mark this lcore as "in use"; this will cause the service
120399a2dd95SBruce Richardson * function to process the timer list that corresponds to this lcore.
120499a2dd95SBruce Richardson * The atomic compare-and-swap operation can prevent the race condition
120599a2dd95SBruce Richardson * on in_use flag between multiple non-EAL threads.
120699a2dd95SBruce Richardson */
1207253de9a8STyler Retzlaff if (unlikely(rte_atomic_compare_exchange_strong_explicit(&sw->in_use[lcore_id].v,
1208253de9a8STyler Retzlaff &exp_state, 1,
1209253de9a8STyler Retzlaff rte_memory_order_relaxed, rte_memory_order_relaxed))) {
121099a2dd95SBruce Richardson EVTIM_LOG_DBG("Adding lcore id = %u to list of lcores to poll",
121199a2dd95SBruce Richardson lcore_id);
1212253de9a8STyler Retzlaff n_lcores = rte_atomic_fetch_add_explicit(&sw->n_poll_lcores, 1,
1213253de9a8STyler Retzlaff rte_memory_order_relaxed);
1214253de9a8STyler Retzlaff rte_atomic_store_explicit(&sw->poll_lcores[n_lcores], lcore_id,
1215253de9a8STyler Retzlaff rte_memory_order_relaxed);
121699a2dd95SBruce Richardson }
121799a2dd95SBruce Richardson
121899a2dd95SBruce Richardson ret = rte_mempool_get_bulk(sw->tim_pool, (void **)tims,
121999a2dd95SBruce Richardson nb_evtims);
122099a2dd95SBruce Richardson if (ret < 0) {
122199a2dd95SBruce Richardson rte_errno = ENOSPC;
122299a2dd95SBruce Richardson return 0;
122399a2dd95SBruce Richardson }
122499a2dd95SBruce Richardson
12253d9d8adfSNaga Harish K S V /* update timer type for periodic adapter */
12263d9d8adfSNaga Harish K S V type = get_timer_type(adapter);
12273d9d8adfSNaga Harish K S V
122899a2dd95SBruce Richardson for (i = 0; i < nb_evtims; i++) {
1229253de9a8STyler Retzlaff n_state = rte_atomic_load_explicit(&evtims[i]->state, rte_memory_order_acquire);
123099a2dd95SBruce Richardson if (n_state == RTE_EVENT_TIMER_ARMED) {
123199a2dd95SBruce Richardson rte_errno = EALREADY;
123299a2dd95SBruce Richardson break;
123399a2dd95SBruce Richardson } else if (!(n_state == RTE_EVENT_TIMER_NOT_ARMED ||
123499a2dd95SBruce Richardson n_state == RTE_EVENT_TIMER_CANCELED)) {
123599a2dd95SBruce Richardson rte_errno = EINVAL;
123699a2dd95SBruce Richardson break;
123799a2dd95SBruce Richardson }
123899a2dd95SBruce Richardson
123999a2dd95SBruce Richardson if (unlikely(check_destination_event_queue(evtims[i],
124099a2dd95SBruce Richardson adapter) < 0)) {
1241253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state,
124299a2dd95SBruce Richardson RTE_EVENT_TIMER_ERROR,
1243253de9a8STyler Retzlaff rte_memory_order_relaxed);
124499a2dd95SBruce Richardson rte_errno = EINVAL;
124599a2dd95SBruce Richardson break;
124699a2dd95SBruce Richardson }
124799a2dd95SBruce Richardson
124899a2dd95SBruce Richardson tim = tims[i];
124999a2dd95SBruce Richardson rte_timer_init(tim);
125099a2dd95SBruce Richardson
125199a2dd95SBruce Richardson evtims[i]->impl_opaque[0] = (uintptr_t)tim;
125299a2dd95SBruce Richardson evtims[i]->impl_opaque[1] = (uintptr_t)adapter;
125399a2dd95SBruce Richardson
125413aba5f8SErik Gabriel Carrillo ret = get_timeout_cycles(evtims[i], adapter, &cycles);
125513aba5f8SErik Gabriel Carrillo if (unlikely(ret == -1)) {
1256253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state,
125713aba5f8SErik Gabriel Carrillo RTE_EVENT_TIMER_ERROR_TOOLATE,
1258253de9a8STyler Retzlaff rte_memory_order_relaxed);
125913aba5f8SErik Gabriel Carrillo rte_errno = EINVAL;
126013aba5f8SErik Gabriel Carrillo break;
126113aba5f8SErik Gabriel Carrillo } else if (unlikely(ret == -2)) {
1262253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state,
126313aba5f8SErik Gabriel Carrillo RTE_EVENT_TIMER_ERROR_TOOEARLY,
1264253de9a8STyler Retzlaff rte_memory_order_relaxed);
126513aba5f8SErik Gabriel Carrillo rte_errno = EINVAL;
126613aba5f8SErik Gabriel Carrillo break;
126713aba5f8SErik Gabriel Carrillo }
126813aba5f8SErik Gabriel Carrillo
126999a2dd95SBruce Richardson ret = rte_timer_alt_reset(sw->timer_data_id, tim, cycles,
12703d9d8adfSNaga Harish K S V type, lcore_id, NULL, evtims[i]);
127199a2dd95SBruce Richardson if (ret < 0) {
127299a2dd95SBruce Richardson /* tim was in RUNNING or CONFIG state */
1273253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state,
127499a2dd95SBruce Richardson RTE_EVENT_TIMER_ERROR,
1275253de9a8STyler Retzlaff rte_memory_order_release);
127699a2dd95SBruce Richardson break;
127799a2dd95SBruce Richardson }
127899a2dd95SBruce Richardson
127999a2dd95SBruce Richardson EVTIM_LOG_DBG("armed an event timer");
128099a2dd95SBruce Richardson /* RELEASE ordering guarantees the adapter specific value
128199a2dd95SBruce Richardson * changes observed before the update of state.
128299a2dd95SBruce Richardson */
1283253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state, RTE_EVENT_TIMER_ARMED,
1284253de9a8STyler Retzlaff rte_memory_order_release);
128599a2dd95SBruce Richardson }
128699a2dd95SBruce Richardson
128799a2dd95SBruce Richardson if (i < nb_evtims)
128899a2dd95SBruce Richardson rte_mempool_put_bulk(sw->tim_pool,
128999a2dd95SBruce Richardson (void **)&tims[i], nb_evtims - i);
129099a2dd95SBruce Richardson
129199a2dd95SBruce Richardson return i;
129299a2dd95SBruce Richardson }
129399a2dd95SBruce Richardson
129499a2dd95SBruce Richardson static uint16_t
swtim_arm_burst(const struct rte_event_timer_adapter * adapter,struct rte_event_timer ** evtims,uint16_t nb_evtims)129599a2dd95SBruce Richardson swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
129699a2dd95SBruce Richardson struct rte_event_timer **evtims,
129799a2dd95SBruce Richardson uint16_t nb_evtims)
129899a2dd95SBruce Richardson {
129999a2dd95SBruce Richardson return __swtim_arm_burst(adapter, evtims, nb_evtims);
130099a2dd95SBruce Richardson }
130199a2dd95SBruce Richardson
130299a2dd95SBruce Richardson static uint16_t
swtim_cancel_burst(const struct rte_event_timer_adapter * adapter,struct rte_event_timer ** evtims,uint16_t nb_evtims)130399a2dd95SBruce Richardson swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
130499a2dd95SBruce Richardson struct rte_event_timer **evtims,
130599a2dd95SBruce Richardson uint16_t nb_evtims)
130699a2dd95SBruce Richardson {
130799a2dd95SBruce Richardson int i, ret;
130899a2dd95SBruce Richardson struct rte_timer *timp;
130999a2dd95SBruce Richardson uint64_t opaque;
131099a2dd95SBruce Richardson struct swtim *sw = swtim_pmd_priv(adapter);
131199a2dd95SBruce Richardson enum rte_event_timer_state n_state;
131299a2dd95SBruce Richardson
131399a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
131499a2dd95SBruce Richardson /* Check that the service is running. */
131599a2dd95SBruce Richardson if (rte_service_runstate_get(adapter->data->service_id) != 1) {
131699a2dd95SBruce Richardson rte_errno = EINVAL;
131799a2dd95SBruce Richardson return 0;
131899a2dd95SBruce Richardson }
131999a2dd95SBruce Richardson #endif
132099a2dd95SBruce Richardson
132199a2dd95SBruce Richardson for (i = 0; i < nb_evtims; i++) {
132299a2dd95SBruce Richardson /* Don't modify the event timer state in these cases */
132399a2dd95SBruce Richardson /* ACQUIRE ordering guarantees the access of implementation
132499a2dd95SBruce Richardson * specific opaque data under the correct state.
132599a2dd95SBruce Richardson */
1326253de9a8STyler Retzlaff n_state = rte_atomic_load_explicit(&evtims[i]->state, rte_memory_order_acquire);
132799a2dd95SBruce Richardson if (n_state == RTE_EVENT_TIMER_CANCELED) {
132899a2dd95SBruce Richardson rte_errno = EALREADY;
132999a2dd95SBruce Richardson break;
133099a2dd95SBruce Richardson } else if (n_state != RTE_EVENT_TIMER_ARMED) {
133199a2dd95SBruce Richardson rte_errno = EINVAL;
133299a2dd95SBruce Richardson break;
133399a2dd95SBruce Richardson }
133499a2dd95SBruce Richardson
133599a2dd95SBruce Richardson opaque = evtims[i]->impl_opaque[0];
133699a2dd95SBruce Richardson timp = (struct rte_timer *)(uintptr_t)opaque;
133799a2dd95SBruce Richardson RTE_ASSERT(timp != NULL);
133899a2dd95SBruce Richardson
133999a2dd95SBruce Richardson ret = rte_timer_alt_stop(sw->timer_data_id, timp);
134099a2dd95SBruce Richardson if (ret < 0) {
134199a2dd95SBruce Richardson /* Timer is running or being configured */
134299a2dd95SBruce Richardson rte_errno = EAGAIN;
134399a2dd95SBruce Richardson break;
134499a2dd95SBruce Richardson }
134599a2dd95SBruce Richardson
134699a2dd95SBruce Richardson rte_mempool_put(sw->tim_pool, (void **)timp);
134799a2dd95SBruce Richardson
134899a2dd95SBruce Richardson /* The RELEASE ordering here pairs with atomic ordering
134999a2dd95SBruce Richardson * to make sure the state update data observed between
135099a2dd95SBruce Richardson * threads.
135199a2dd95SBruce Richardson */
1352253de9a8STyler Retzlaff rte_atomic_store_explicit(&evtims[i]->state, RTE_EVENT_TIMER_CANCELED,
1353253de9a8STyler Retzlaff rte_memory_order_release);
135499a2dd95SBruce Richardson }
135599a2dd95SBruce Richardson
135699a2dd95SBruce Richardson return i;
135799a2dd95SBruce Richardson }
135899a2dd95SBruce Richardson
135999a2dd95SBruce Richardson static uint16_t
swtim_arm_tmo_tick_burst(const struct rte_event_timer_adapter * adapter,struct rte_event_timer ** evtims,uint64_t timeout_ticks,uint16_t nb_evtims)136099a2dd95SBruce Richardson swtim_arm_tmo_tick_burst(const struct rte_event_timer_adapter *adapter,
136199a2dd95SBruce Richardson struct rte_event_timer **evtims,
136299a2dd95SBruce Richardson uint64_t timeout_ticks,
136399a2dd95SBruce Richardson uint16_t nb_evtims)
136499a2dd95SBruce Richardson {
136599a2dd95SBruce Richardson int i;
136699a2dd95SBruce Richardson
136799a2dd95SBruce Richardson for (i = 0; i < nb_evtims; i++)
136899a2dd95SBruce Richardson evtims[i]->timeout_ticks = timeout_ticks;
136999a2dd95SBruce Richardson
137099a2dd95SBruce Richardson return __swtim_arm_burst(adapter, evtims, nb_evtims);
137199a2dd95SBruce Richardson }
137299a2dd95SBruce Richardson
137353548ad3SPavan Nikhilesh static const struct event_timer_adapter_ops swtim_ops = {
137499a2dd95SBruce Richardson .init = swtim_init,
137599a2dd95SBruce Richardson .uninit = swtim_uninit,
137699a2dd95SBruce Richardson .start = swtim_start,
137799a2dd95SBruce Richardson .stop = swtim_stop,
137899a2dd95SBruce Richardson .get_info = swtim_get_info,
137999a2dd95SBruce Richardson .stats_get = swtim_stats_get,
138099a2dd95SBruce Richardson .stats_reset = swtim_stats_reset,
138199a2dd95SBruce Richardson .arm_burst = swtim_arm_burst,
138299a2dd95SBruce Richardson .arm_tmo_tick_burst = swtim_arm_tmo_tick_burst,
138399a2dd95SBruce Richardson .cancel_burst = swtim_cancel_burst,
13840727ff34SErik Gabriel Carrillo .remaining_ticks_get = swtim_remaining_ticks_get,
138599a2dd95SBruce Richardson };
1386791dfec2SAnkur Dwivedi
1387791dfec2SAnkur Dwivedi static int
handle_ta_info(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)1388791dfec2SAnkur Dwivedi handle_ta_info(const char *cmd __rte_unused, const char *params,
1389791dfec2SAnkur Dwivedi struct rte_tel_data *d)
1390791dfec2SAnkur Dwivedi {
1391791dfec2SAnkur Dwivedi struct rte_event_timer_adapter_info adapter_info;
1392791dfec2SAnkur Dwivedi struct rte_event_timer_adapter *adapter;
1393791dfec2SAnkur Dwivedi uint16_t adapter_id;
1394791dfec2SAnkur Dwivedi int ret;
1395791dfec2SAnkur Dwivedi
1396791dfec2SAnkur Dwivedi if (params == NULL || strlen(params) == 0 || !isdigit(*params))
1397791dfec2SAnkur Dwivedi return -1;
1398791dfec2SAnkur Dwivedi
1399791dfec2SAnkur Dwivedi adapter_id = atoi(params);
1400791dfec2SAnkur Dwivedi
1401791dfec2SAnkur Dwivedi if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
1402791dfec2SAnkur Dwivedi EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
1403791dfec2SAnkur Dwivedi return -EINVAL;
1404791dfec2SAnkur Dwivedi }
1405791dfec2SAnkur Dwivedi
1406791dfec2SAnkur Dwivedi adapter = &adapters[adapter_id];
1407791dfec2SAnkur Dwivedi
1408791dfec2SAnkur Dwivedi ret = rte_event_timer_adapter_get_info(adapter, &adapter_info);
1409791dfec2SAnkur Dwivedi if (ret < 0) {
1410791dfec2SAnkur Dwivedi EVTIM_LOG_ERR("Failed to get info for timer adapter id %u", adapter_id);
1411791dfec2SAnkur Dwivedi return ret;
1412791dfec2SAnkur Dwivedi }
1413791dfec2SAnkur Dwivedi
1414791dfec2SAnkur Dwivedi rte_tel_data_start_dict(d);
1415af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
1416af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "min_resolution_ns",
1417af0785a2SBruce Richardson adapter_info.min_resolution_ns);
1418af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "max_tmo_ns", adapter_info.max_tmo_ns);
1419af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "event_dev_id",
1420af0785a2SBruce Richardson adapter_info.conf.event_dev_id);
1421af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "socket_id",
1422af0785a2SBruce Richardson adapter_info.conf.socket_id);
1423af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "clk_src", adapter_info.conf.clk_src);
1424af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "timer_tick_ns",
1425af0785a2SBruce Richardson adapter_info.conf.timer_tick_ns);
1426af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "nb_timers",
1427af0785a2SBruce Richardson adapter_info.conf.nb_timers);
1428af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "flags", adapter_info.conf.flags);
1429791dfec2SAnkur Dwivedi
1430791dfec2SAnkur Dwivedi return 0;
1431791dfec2SAnkur Dwivedi }
1432791dfec2SAnkur Dwivedi
1433791dfec2SAnkur Dwivedi static int
handle_ta_stats(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)1434791dfec2SAnkur Dwivedi handle_ta_stats(const char *cmd __rte_unused, const char *params,
1435791dfec2SAnkur Dwivedi struct rte_tel_data *d)
1436791dfec2SAnkur Dwivedi {
1437791dfec2SAnkur Dwivedi struct rte_event_timer_adapter_stats stats;
1438791dfec2SAnkur Dwivedi struct rte_event_timer_adapter *adapter;
1439791dfec2SAnkur Dwivedi uint16_t adapter_id;
1440791dfec2SAnkur Dwivedi int ret;
1441791dfec2SAnkur Dwivedi
1442791dfec2SAnkur Dwivedi if (params == NULL || strlen(params) == 0 || !isdigit(*params))
1443791dfec2SAnkur Dwivedi return -1;
1444791dfec2SAnkur Dwivedi
1445791dfec2SAnkur Dwivedi adapter_id = atoi(params);
1446791dfec2SAnkur Dwivedi
1447791dfec2SAnkur Dwivedi if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
1448791dfec2SAnkur Dwivedi EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
1449791dfec2SAnkur Dwivedi return -EINVAL;
1450791dfec2SAnkur Dwivedi }
1451791dfec2SAnkur Dwivedi
1452791dfec2SAnkur Dwivedi adapter = &adapters[adapter_id];
1453791dfec2SAnkur Dwivedi
1454791dfec2SAnkur Dwivedi ret = rte_event_timer_adapter_stats_get(adapter, &stats);
1455791dfec2SAnkur Dwivedi if (ret < 0) {
1456791dfec2SAnkur Dwivedi EVTIM_LOG_ERR("Failed to get stats for timer adapter id %u", adapter_id);
1457791dfec2SAnkur Dwivedi return ret;
1458791dfec2SAnkur Dwivedi }
1459791dfec2SAnkur Dwivedi
1460791dfec2SAnkur Dwivedi rte_tel_data_start_dict(d);
1461af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
1462af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "evtim_exp_count",
1463af0785a2SBruce Richardson stats.evtim_exp_count);
1464af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "ev_enq_count", stats.ev_enq_count);
1465af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "ev_inv_count", stats.ev_inv_count);
1466af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "evtim_retry_count",
1467af0785a2SBruce Richardson stats.evtim_retry_count);
1468af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, "adapter_tick_count",
1469af0785a2SBruce Richardson stats.adapter_tick_count);
1470791dfec2SAnkur Dwivedi
1471791dfec2SAnkur Dwivedi return 0;
1472791dfec2SAnkur Dwivedi }
1473791dfec2SAnkur Dwivedi
RTE_INIT(ta_init_telemetry)1474791dfec2SAnkur Dwivedi RTE_INIT(ta_init_telemetry)
1475791dfec2SAnkur Dwivedi {
1476791dfec2SAnkur Dwivedi rte_telemetry_register_cmd("/eventdev/ta_info",
1477791dfec2SAnkur Dwivedi handle_ta_info,
1478791dfec2SAnkur Dwivedi "Returns Timer adapter info. Parameter: Timer adapter id");
1479791dfec2SAnkur Dwivedi
1480791dfec2SAnkur Dwivedi rte_telemetry_register_cmd("/eventdev/ta_stats",
1481791dfec2SAnkur Dwivedi handle_ta_stats,
1482791dfec2SAnkur Dwivedi "Returns Timer adapter stats. Parameter: Timer adapter id");
1483791dfec2SAnkur Dwivedi }
1484