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