LCOV - code coverage report
Current view: top level - lib/eventdev - rte_event_timer_adapter.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 7 539 1.3 %
Date: 2025-05-01 17:49:45 Functions: 4 36 11.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 3 328 0.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2017-2018 Intel Corporation.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <ctype.h>
       7                 :            : #include <string.h>
       8                 :            : #include <inttypes.h>
       9                 :            : #include <stdalign.h>
      10                 :            : #include <stdbool.h>
      11                 :            : #include <stdlib.h>
      12                 :            : #include <math.h>
      13                 :            : 
      14                 :            : #include <eal_export.h>
      15                 :            : #include <rte_memzone.h>
      16                 :            : #include <rte_errno.h>
      17                 :            : #include <rte_malloc.h>
      18                 :            : #include <rte_mempool.h>
      19                 :            : #include <rte_common.h>
      20                 :            : #include <rte_timer.h>
      21                 :            : #include <rte_service_component.h>
      22                 :            : #include <rte_telemetry.h>
      23                 :            : #include <rte_reciprocal.h>
      24                 :            : 
      25                 :            : #include "event_timer_adapter_pmd.h"
      26                 :            : #include "eventdev_pmd.h"
      27                 :            : #include "rte_event_timer_adapter.h"
      28                 :            : #include "rte_eventdev.h"
      29                 :            : #include "eventdev_trace.h"
      30                 :            : 
      31                 :            : #define DATA_MZ_NAME_MAX_LEN 64
      32                 :            : #define DATA_MZ_NAME_FORMAT "rte_event_timer_adapter_data_%d"
      33                 :            : 
      34         [ -  + ]:        252 : RTE_LOG_REGISTER_SUFFIX(evtim_logtype, adapter.timer, NOTICE);
      35                 :            : #define RTE_LOGTYPE_EVTIM evtim_logtype
      36         [ -  + ]:        252 : RTE_LOG_REGISTER_SUFFIX(evtim_buffer_logtype, adapter.timer, NOTICE);
      37                 :            : #define RTE_LOGTYPE_EVTIM_BUF evtim_buffer_logtype
      38         [ -  + ]:        252 : RTE_LOG_REGISTER_SUFFIX(evtim_svc_logtype, adapter.timer.svc, NOTICE);
      39                 :            : #define RTE_LOGTYPE_EVTIM_SVC evtim_svc_logtype
      40                 :            : 
      41                 :            : static struct rte_event_timer_adapter *adapters;
      42                 :            : 
      43                 :            : static const struct event_timer_adapter_ops swtim_ops;
      44                 :            : 
      45                 :            : #define EVTIM_LOG(level, logtype, ...) \
      46                 :            :         RTE_LOG_LINE_PREFIX(level, logtype, \
      47                 :            :                 "EVTIMER: %s() line %u: ", __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
      48                 :            : 
      49                 :            : #define EVTIM_LOG_ERR(...) EVTIM_LOG(ERR, EVTIM, __VA_ARGS__)
      50                 :            : 
      51                 :            : #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
      52                 :            : #define EVTIM_LOG_DBG(...) \
      53                 :            :         EVTIM_LOG(DEBUG, EVTIM, __VA_ARGS__)
      54                 :            : #define EVTIM_BUF_LOG_DBG(...) \
      55                 :            :         EVTIM_LOG(DEBUG, EVTIM_BUF, __VA_ARGS__)
      56                 :            : #define EVTIM_SVC_LOG_DBG(...) \
      57                 :            :         EVTIM_LOG(DEBUG, EVTIM_SVC, __VA_ARGS__)
      58                 :            : #else
      59                 :            : #define EVTIM_LOG_DBG(...) (void)0
      60                 :            : #define EVTIM_BUF_LOG_DBG(...) (void)0
      61                 :            : #define EVTIM_SVC_LOG_DBG(...) (void)0
      62                 :            : #endif
      63                 :            : 
      64                 :            : static inline enum rte_timer_type
      65                 :            : get_timer_type(const struct rte_event_timer_adapter *adapter)
      66                 :            : {
      67                 :          0 :         return (adapter->data->conf.flags &
      68                 :            :                         RTE_EVENT_TIMER_ADAPTER_F_PERIODIC) ?
      69                 :          0 :                         PERIODICAL : SINGLE;
      70                 :            : }
      71                 :            : 
      72                 :            : static int
      73                 :          0 : default_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id,
      74                 :            :                      void *conf_arg)
      75                 :            : {
      76                 :            :         struct rte_event_timer_adapter *adapter;
      77                 :            :         struct rte_eventdev *dev;
      78                 :            :         struct rte_event_dev_config dev_conf;
      79                 :          0 :         struct rte_event_port_conf *port_conf, def_port_conf = {0};
      80                 :            :         int started;
      81                 :            :         uint8_t port_id;
      82                 :            :         uint8_t dev_id;
      83                 :            :         int ret;
      84                 :            : 
      85                 :            :         RTE_SET_USED(event_dev_id);
      86                 :            : 
      87                 :          0 :         adapter = &adapters[id];
      88                 :          0 :         dev = &rte_eventdevs[adapter->data->event_dev_id];
      89                 :          0 :         dev_id = dev->data->dev_id;
      90                 :          0 :         dev_conf = dev->data->dev_conf;
      91                 :            : 
      92                 :          0 :         started = dev->data->dev_started;
      93         [ #  # ]:          0 :         if (started)
      94                 :          0 :                 rte_event_dev_stop(dev_id);
      95                 :            : 
      96                 :          0 :         port_id = dev_conf.nb_event_ports;
      97         [ #  # ]:          0 :         if (conf_arg != NULL)
      98                 :            :                 port_conf = conf_arg;
      99                 :            :         else {
     100                 :            :                 port_conf = &def_port_conf;
     101                 :          0 :                 ret = rte_event_port_default_conf_get(dev_id, (port_id - 1),
     102                 :            :                                                       port_conf);
     103         [ #  # ]:          0 :                 if (ret < 0)
     104                 :            :                         return ret;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         dev_conf.nb_event_ports += 1;
     108         [ #  # ]:          0 :         if (port_conf->event_port_cfg & RTE_EVENT_PORT_CFG_SINGLE_LINK)
     109                 :          0 :                 dev_conf.nb_single_link_event_port_queues += 1;
     110                 :            : 
     111                 :          0 :         ret = rte_event_dev_configure(dev_id, &dev_conf);
     112         [ #  # ]:          0 :         if (ret < 0) {
     113                 :          0 :                 EVTIM_LOG_ERR("failed to configure event dev %u", dev_id);
     114         [ #  # ]:          0 :                 if (started)
     115         [ #  # ]:          0 :                         if (rte_event_dev_start(dev_id))
     116                 :            :                                 return -EIO;
     117                 :            : 
     118                 :          0 :                 return ret;
     119                 :            :         }
     120                 :            : 
     121                 :          0 :         ret = rte_event_port_setup(dev_id, port_id, port_conf);
     122         [ #  # ]:          0 :         if (ret < 0) {
     123                 :          0 :                 EVTIM_LOG_ERR("failed to setup event port %u on event dev %u",
     124                 :            :                               port_id, dev_id);
     125                 :          0 :                 return ret;
     126                 :            :         }
     127                 :            : 
     128                 :          0 :         *event_port_id = port_id;
     129                 :            : 
     130         [ #  # ]:          0 :         if (started)
     131                 :          0 :                 ret = rte_event_dev_start(dev_id);
     132                 :            : 
     133                 :            :         return ret;
     134                 :            : }
     135                 :            : 
     136                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_create)
     137                 :            : struct rte_event_timer_adapter *
     138                 :          0 : rte_event_timer_adapter_create(const struct rte_event_timer_adapter_conf *conf)
     139                 :            : {
     140                 :          0 :         return rte_event_timer_adapter_create_ext(conf, default_port_conf_cb,
     141                 :            :                                                   NULL);
     142                 :            : }
     143                 :            : 
     144                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_create_ext)
     145                 :            : struct rte_event_timer_adapter *
     146                 :          0 : rte_event_timer_adapter_create_ext(
     147                 :            :                 const struct rte_event_timer_adapter_conf *conf,
     148                 :            :                 rte_event_timer_adapter_port_conf_cb_t conf_cb,
     149                 :            :                 void *conf_arg)
     150                 :            : {
     151                 :            :         uint16_t adapter_id;
     152                 :            :         struct rte_event_timer_adapter *adapter;
     153                 :            :         const struct rte_memzone *mz;
     154                 :            :         char mz_name[DATA_MZ_NAME_MAX_LEN];
     155                 :            :         int n, ret;
     156                 :            :         struct rte_eventdev *dev;
     157                 :            : 
     158         [ #  # ]:          0 :         if (adapters == NULL) {
     159                 :          0 :                 adapters = rte_zmalloc("Eventdev",
     160                 :            :                                        sizeof(struct rte_event_timer_adapter) *
     161                 :            :                                                RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
     162                 :            :                                        RTE_CACHE_LINE_SIZE);
     163         [ #  # ]:          0 :                 if (adapters == NULL) {
     164                 :          0 :                         rte_errno = ENOMEM;
     165                 :          0 :                         return NULL;
     166                 :            :                 }
     167                 :            :         }
     168                 :            : 
     169         [ #  # ]:          0 :         if (conf == NULL) {
     170                 :          0 :                 rte_errno = EINVAL;
     171                 :          0 :                 return NULL;
     172                 :            :         }
     173                 :            : 
     174                 :            :         /* Check eventdev ID */
     175         [ #  # ]:          0 :         if (!rte_event_pmd_is_valid_dev(conf->event_dev_id)) {
     176                 :          0 :                 rte_errno = EINVAL;
     177                 :          0 :                 return NULL;
     178                 :            :         }
     179                 :            :         dev = &rte_eventdevs[conf->event_dev_id];
     180                 :            : 
     181                 :          0 :         adapter_id = conf->timer_adapter_id;
     182                 :            : 
     183                 :            :         /* Check that adapter_id is in range */
     184         [ #  # ]:          0 :         if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
     185                 :          0 :                 rte_errno = EINVAL;
     186                 :          0 :                 return NULL;
     187                 :            :         }
     188                 :            : 
     189                 :            :         /* Check adapter ID not already allocated */
     190                 :          0 :         adapter = &adapters[adapter_id];
     191         [ #  # ]:          0 :         if (adapter->allocated) {
     192                 :          0 :                 rte_errno = EEXIST;
     193                 :          0 :                 return NULL;
     194                 :            :         }
     195                 :            : 
     196                 :            :         /* Create shared data area. */
     197         [ #  # ]:          0 :         n = snprintf(mz_name, sizeof(mz_name), DATA_MZ_NAME_FORMAT, adapter_id);
     198         [ #  # ]:          0 :         if (n >= (int)sizeof(mz_name)) {
     199                 :          0 :                 rte_errno = EINVAL;
     200                 :          0 :                 return NULL;
     201                 :            :         }
     202                 :          0 :         mz = rte_memzone_reserve(mz_name,
     203                 :            :                                  sizeof(struct rte_event_timer_adapter_data),
     204                 :          0 :                                  conf->socket_id, 0);
     205         [ #  # ]:          0 :         if (mz == NULL)
     206                 :            :                 /* rte_errno set by rte_memzone_reserve */
     207                 :            :                 return NULL;
     208                 :            : 
     209         [ #  # ]:          0 :         adapter->data = mz->addr;
     210                 :            :         memset(adapter->data, 0, sizeof(struct rte_event_timer_adapter_data));
     211                 :            : 
     212                 :          0 :         adapter->data->mz = mz;
     213                 :          0 :         adapter->data->event_dev_id = conf->event_dev_id;
     214                 :          0 :         adapter->data->id = adapter_id;
     215                 :          0 :         adapter->data->socket_id = conf->socket_id;
     216                 :          0 :         adapter->data->conf = *conf;  /* copy conf structure */
     217                 :            : 
     218                 :            :         /* Query eventdev PMD for timer adapter capabilities and ops */
     219         [ #  # ]:          0 :         if (dev->dev_ops->timer_adapter_caps_get) {
     220                 :          0 :                 ret = dev->dev_ops->timer_adapter_caps_get(dev,
     221                 :            :                                 adapter->data->conf.flags,
     222                 :            :                                 &adapter->data->caps, &adapter->ops);
     223         [ #  # ]:          0 :                 if (ret < 0) {
     224                 :          0 :                         rte_errno = -ret;
     225                 :          0 :                         goto free_memzone;
     226                 :            :                 }
     227                 :            :         }
     228                 :            : 
     229         [ #  # ]:          0 :         if (!(adapter->data->caps &
     230                 :            :               RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
     231         [ #  # ]:          0 :                 FUNC_PTR_OR_NULL_RET_WITH_ERRNO(conf_cb, EINVAL);
     232                 :          0 :                 ret = conf_cb(adapter->data->id, adapter->data->event_dev_id,
     233                 :            :                               &adapter->data->event_port_id, conf_arg);
     234         [ #  # ]:          0 :                 if (ret < 0) {
     235                 :          0 :                         rte_errno = -ret;
     236                 :          0 :                         goto free_memzone;
     237                 :            :                 }
     238                 :            :         }
     239                 :            : 
     240                 :            :         /* If eventdev PMD did not provide ops, use default software
     241                 :            :          * implementation.
     242                 :            :          */
     243         [ #  # ]:          0 :         if (adapter->ops == NULL)
     244                 :          0 :                 adapter->ops = &swtim_ops;
     245                 :            : 
     246                 :            :         /* Allow driver to do some setup */
     247         [ #  # ]:          0 :         FUNC_PTR_OR_NULL_RET_WITH_ERRNO(adapter->ops->init, ENOTSUP);
     248                 :          0 :         ret = adapter->ops->init(adapter);
     249         [ #  # ]:          0 :         if (ret < 0) {
     250                 :          0 :                 rte_errno = -ret;
     251                 :          0 :                 goto free_memzone;
     252                 :            :         }
     253                 :            : 
     254                 :            :         /* Set fast-path function pointers */
     255                 :          0 :         adapter->arm_burst = adapter->ops->arm_burst;
     256                 :          0 :         adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
     257                 :          0 :         adapter->cancel_burst = adapter->ops->cancel_burst;
     258                 :            : 
     259         [ #  # ]:          0 :         adapter->allocated = 1;
     260                 :            : 
     261                 :          0 :         rte_eventdev_trace_timer_adapter_create(adapter_id, adapter, conf,
     262                 :            :                 conf_cb);
     263                 :          0 :         return adapter;
     264                 :            : 
     265                 :          0 : free_memzone:
     266                 :          0 :         rte_memzone_free(adapter->data->mz);
     267                 :          0 :         return NULL;
     268                 :            : }
     269                 :            : 
     270                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_get_info)
     271                 :            : int
     272                 :          0 : rte_event_timer_adapter_get_info(const struct rte_event_timer_adapter *adapter,
     273                 :            :                 struct rte_event_timer_adapter_info *adapter_info)
     274                 :            : {
     275   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     276                 :            : 
     277         [ #  # ]:          0 :         if (adapter->ops->get_info)
     278                 :            :                 /* let driver set values it knows */
     279                 :          0 :                 adapter->ops->get_info(adapter, adapter_info);
     280                 :            : 
     281                 :            :         /* Set common values */
     282                 :          0 :         adapter_info->conf = adapter->data->conf;
     283                 :          0 :         adapter_info->event_dev_port_id = adapter->data->event_port_id;
     284         [ #  # ]:          0 :         adapter_info->caps = adapter->data->caps;
     285                 :            : 
     286                 :          0 :         rte_eventdev_trace_timer_adapter_get_info(adapter, adapter_info);
     287                 :            : 
     288                 :          0 :         return 0;
     289                 :            : }
     290                 :            : 
     291                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_start)
     292                 :            : int
     293                 :          0 : rte_event_timer_adapter_start(const struct rte_event_timer_adapter *adapter)
     294                 :            : {
     295                 :            :         int ret;
     296                 :            : 
     297   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     298         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->start, -EINVAL);
     299                 :            : 
     300         [ #  # ]:          0 :         if (adapter->data->started) {
     301                 :          0 :                 EVTIM_LOG_ERR("event timer adapter %"PRIu8" already started",
     302                 :            :                               adapter->data->id);
     303                 :          0 :                 return -EALREADY;
     304                 :            :         }
     305                 :            : 
     306                 :          0 :         ret = adapter->ops->start(adapter);
     307         [ #  # ]:          0 :         if (ret < 0)
     308                 :            :                 return ret;
     309                 :            : 
     310         [ #  # ]:          0 :         adapter->data->started = 1;
     311                 :          0 :         rte_eventdev_trace_timer_adapter_start(adapter);
     312                 :          0 :         return 0;
     313                 :            : }
     314                 :            : 
     315                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_stop)
     316                 :            : int
     317                 :          0 : rte_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter)
     318                 :            : {
     319                 :            :         int ret;
     320                 :            : 
     321   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     322         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->stop, -EINVAL);
     323                 :            : 
     324         [ #  # ]:          0 :         if (adapter->data->started == 0) {
     325                 :          0 :                 EVTIM_LOG_ERR("event timer adapter %"PRIu8" already stopped",
     326                 :            :                               adapter->data->id);
     327                 :          0 :                 return 0;
     328                 :            :         }
     329                 :            : 
     330                 :          0 :         ret = adapter->ops->stop(adapter);
     331         [ #  # ]:          0 :         if (ret < 0)
     332                 :            :                 return ret;
     333                 :            : 
     334         [ #  # ]:          0 :         adapter->data->started = 0;
     335                 :          0 :         rte_eventdev_trace_timer_adapter_stop(adapter);
     336                 :          0 :         return 0;
     337                 :            : }
     338                 :            : 
     339                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_lookup)
     340                 :            : struct rte_event_timer_adapter *
     341                 :          0 : rte_event_timer_adapter_lookup(uint16_t adapter_id)
     342                 :            : {
     343                 :            :         char name[DATA_MZ_NAME_MAX_LEN];
     344                 :            :         const struct rte_memzone *mz;
     345                 :            :         struct rte_event_timer_adapter_data *data;
     346                 :            :         struct rte_event_timer_adapter *adapter;
     347                 :            :         int ret;
     348                 :            :         struct rte_eventdev *dev;
     349                 :            : 
     350         [ #  # ]:          0 :         if (adapters == NULL) {
     351                 :          0 :                 adapters = rte_zmalloc("Eventdev",
     352                 :            :                                        sizeof(struct rte_event_timer_adapter) *
     353                 :            :                                                RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
     354                 :            :                                        RTE_CACHE_LINE_SIZE);
     355         [ #  # ]:          0 :                 if (adapters == NULL) {
     356                 :          0 :                         rte_errno = ENOMEM;
     357                 :          0 :                         return NULL;
     358                 :            :                 }
     359                 :            :         }
     360                 :            : 
     361         [ #  # ]:          0 :         if (adapters[adapter_id].allocated)
     362                 :            :                 return &adapters[adapter_id]; /* Adapter is already loaded */
     363                 :            : 
     364                 :          0 :         snprintf(name, DATA_MZ_NAME_MAX_LEN, DATA_MZ_NAME_FORMAT, adapter_id);
     365                 :          0 :         mz = rte_memzone_lookup(name);
     366         [ #  # ]:          0 :         if (mz == NULL) {
     367                 :          0 :                 rte_errno = ENOENT;
     368                 :          0 :                 return NULL;
     369                 :            :         }
     370                 :            : 
     371                 :          0 :         data = mz->addr;
     372                 :            : 
     373                 :          0 :         adapter = &adapters[data->id];
     374                 :          0 :         adapter->data = data;
     375                 :            : 
     376                 :          0 :         dev = &rte_eventdevs[adapter->data->event_dev_id];
     377                 :            : 
     378                 :            :         /* Query eventdev PMD for timer adapter capabilities and ops */
     379         [ #  # ]:          0 :         if (dev->dev_ops->timer_adapter_caps_get) {
     380                 :          0 :                 ret = dev->dev_ops->timer_adapter_caps_get(dev,
     381                 :            :                                 adapter->data->conf.flags,
     382                 :            :                                 &adapter->data->caps, &adapter->ops);
     383         [ #  # ]:          0 :                 if (ret < 0) {
     384                 :          0 :                         rte_errno = EINVAL;
     385                 :          0 :                         return NULL;
     386                 :            :                 }
     387                 :            :         }
     388                 :            : 
     389                 :            :         /* If eventdev PMD did not provide ops, use default software
     390                 :            :          * implementation.
     391                 :            :          */
     392         [ #  # ]:          0 :         if (adapter->ops == NULL)
     393                 :          0 :                 adapter->ops = &swtim_ops;
     394                 :            : 
     395                 :            :         /* Set fast-path function pointers */
     396                 :          0 :         adapter->arm_burst = adapter->ops->arm_burst;
     397                 :          0 :         adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst;
     398                 :          0 :         adapter->cancel_burst = adapter->ops->cancel_burst;
     399                 :            : 
     400         [ #  # ]:          0 :         adapter->allocated = 1;
     401                 :            : 
     402                 :          0 :         rte_eventdev_trace_timer_adapter_lookup(adapter_id, adapter);
     403                 :            : 
     404                 :          0 :         return adapter;
     405                 :            : }
     406                 :            : 
     407                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_free)
     408                 :            : int
     409                 :          0 : rte_event_timer_adapter_free(struct rte_event_timer_adapter *adapter)
     410                 :            : {
     411                 :            :         int i, ret;
     412                 :            : 
     413   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     414         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->uninit, -EINVAL);
     415                 :            : 
     416         [ #  # ]:          0 :         if (adapter->data->started == 1) {
     417                 :          0 :                 EVTIM_LOG_ERR("event timer adapter %"PRIu8" must be stopped "
     418                 :            :                               "before freeing", adapter->data->id);
     419                 :          0 :                 return -EBUSY;
     420                 :            :         }
     421                 :            : 
     422                 :            :         /* free impl priv data */
     423                 :          0 :         ret = adapter->ops->uninit(adapter);
     424         [ #  # ]:          0 :         if (ret < 0)
     425                 :            :                 return ret;
     426                 :            : 
     427                 :            :         /* free shared data area */
     428                 :          0 :         ret = rte_memzone_free(adapter->data->mz);
     429         [ #  # ]:          0 :         if (ret < 0)
     430                 :            :                 return ret;
     431                 :            : 
     432                 :          0 :         adapter->data = NULL;
     433                 :          0 :         adapter->allocated = 0;
     434                 :            : 
     435                 :            :         ret = 0;
     436         [ #  # ]:          0 :         for (i = 0; i < RTE_EVENT_TIMER_ADAPTER_NUM_MAX; i++)
     437         [ #  # ]:          0 :                 if (adapters[i].allocated)
     438                 :          0 :                         ret = adapters[i].allocated;
     439                 :            : 
     440         [ #  # ]:          0 :         if (!ret) {
     441                 :          0 :                 rte_free(adapters);
     442                 :          0 :                 adapters = NULL;
     443                 :            :         }
     444                 :            : 
     445                 :          0 :         rte_eventdev_trace_timer_adapter_free(adapter);
     446                 :          0 :         return 0;
     447                 :            : }
     448                 :            : 
     449                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_service_id_get)
     450                 :            : int
     451                 :          0 : rte_event_timer_adapter_service_id_get(struct rte_event_timer_adapter *adapter,
     452                 :            :                                        uint32_t *service_id)
     453                 :            : {
     454   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     455                 :            : 
     456         [ #  # ]:          0 :         if (service_id == NULL)
     457                 :            :                 return -EINVAL;
     458                 :            : 
     459         [ #  # ]:          0 :         if (adapter->data->service_inited && service_id != NULL)
     460                 :          0 :                 *service_id = adapter->data->service_id;
     461                 :            : 
     462         [ #  # ]:          0 :         rte_eventdev_trace_timer_adapter_service_id_get(adapter, *service_id);
     463                 :            : 
     464         [ #  # ]:          0 :         return adapter->data->service_inited ? 0 : -ESRCH;
     465                 :            : }
     466                 :            : 
     467                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_stats_get)
     468                 :            : int
     469         [ #  # ]:          0 : rte_event_timer_adapter_stats_get(struct rte_event_timer_adapter *adapter,
     470                 :            :                                   struct rte_event_timer_adapter_stats *stats)
     471                 :            : {
     472                 :          0 :         rte_eventdev_trace_timer_adapter_stats_get(adapter, stats);
     473                 :            : 
     474   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     475         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->stats_get, -EINVAL);
     476         [ #  # ]:          0 :         if (stats == NULL)
     477                 :            :                 return -EINVAL;
     478                 :            : 
     479                 :          0 :         return adapter->ops->stats_get(adapter, stats);
     480                 :            : }
     481                 :            : 
     482                 :            : RTE_EXPORT_SYMBOL(rte_event_timer_adapter_stats_reset)
     483                 :            : int
     484         [ #  # ]:          0 : rte_event_timer_adapter_stats_reset(struct rte_event_timer_adapter *adapter)
     485                 :            : {
     486                 :          0 :         rte_eventdev_trace_timer_adapter_stats_reset(adapter);
     487                 :            : 
     488   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     489         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->stats_reset, -EINVAL);
     490                 :          0 :         return adapter->ops->stats_reset(adapter);
     491                 :            : }
     492                 :            : 
     493                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_event_timer_remaining_ticks_get, 23.03)
     494                 :            : int
     495         [ #  # ]:          0 : rte_event_timer_remaining_ticks_get(
     496                 :            :                         const struct rte_event_timer_adapter *adapter,
     497                 :            :                         const struct rte_event_timer *evtim,
     498                 :            :                         uint64_t *ticks_remaining)
     499                 :            : {
     500                 :          0 :         rte_eventdev_trace_timer_remaining_ticks_get(adapter, evtim, ticks_remaining);
     501                 :            : 
     502   [ #  #  #  # ]:          0 :         ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
     503         [ #  # ]:          0 :         FUNC_PTR_OR_ERR_RET(adapter->ops->remaining_ticks_get, -ENOTSUP);
     504                 :            : 
     505         [ #  # ]:          0 :         if (ticks_remaining == NULL)
     506                 :            :                 return -EINVAL;
     507                 :            : 
     508                 :          0 :         return adapter->ops->remaining_ticks_get(adapter, evtim,
     509                 :            :                                                  ticks_remaining);
     510                 :            : }
     511                 :            : 
     512                 :            : /*
     513                 :            :  * Software event timer adapter buffer helper functions
     514                 :            :  */
     515                 :            : 
     516                 :            : #define NSECPERSEC 1E9
     517                 :            : 
     518                 :            : /* Optimizations used to index into the buffer require that the buffer size
     519                 :            :  * be a power of 2.
     520                 :            :  */
     521                 :            : #define EVENT_BUFFER_SZ 4096
     522                 :            : #define EVENT_BUFFER_BATCHSZ 32
     523                 :            : #define EVENT_BUFFER_MASK (EVENT_BUFFER_SZ - 1)
     524                 :            : 
     525                 :            : #define EXP_TIM_BUF_SZ 128
     526                 :            : 
     527                 :            : struct __rte_cache_aligned event_buffer {
     528                 :            :         size_t head;
     529                 :            :         size_t tail;
     530                 :            :         struct rte_event events[EVENT_BUFFER_SZ];
     531                 :            : };
     532                 :            : 
     533                 :            : static inline bool
     534                 :            : event_buffer_full(struct event_buffer *bufp)
     535                 :            : {
     536                 :          0 :         return (bufp->head - bufp->tail) == EVENT_BUFFER_SZ;
     537                 :            : }
     538                 :            : 
     539                 :            : static inline bool
     540                 :            : event_buffer_batch_ready(struct event_buffer *bufp)
     541                 :            : {
     542                 :          0 :         return (bufp->head - bufp->tail) >= EVENT_BUFFER_BATCHSZ;
     543                 :            : }
     544                 :            : 
     545                 :            : static void
     546                 :            : event_buffer_init(struct event_buffer *bufp)
     547                 :            : {
     548                 :          0 :         bufp->head = bufp->tail = 0;
     549                 :          0 :         memset(&bufp->events, 0, sizeof(struct rte_event) * EVENT_BUFFER_SZ);
     550                 :            : }
     551                 :            : 
     552                 :            : static int
     553                 :            : event_buffer_add(struct event_buffer *bufp, struct rte_event *eventp)
     554                 :            : {
     555                 :            :         size_t head_idx;
     556                 :            :         struct rte_event *buf_eventp;
     557                 :            : 
     558                 :          0 :         if (event_buffer_full(bufp))
     559                 :            :                 return -1;
     560                 :            : 
     561                 :            :         /* Instead of modulus, bitwise AND with mask to get head_idx. */
     562                 :          0 :         head_idx = bufp->head & EVENT_BUFFER_MASK;
     563         [ #  # ]:          0 :         buf_eventp = &bufp->events[head_idx];
     564                 :            :         rte_memcpy(buf_eventp, eventp, sizeof(struct rte_event));
     565                 :            : 
     566                 :            :         /* Wrap automatically when overflow occurs. */
     567                 :          0 :         bufp->head++;
     568                 :            : 
     569                 :            :         return 0;
     570                 :            : }
     571                 :            : 
     572                 :            : static void
     573                 :          0 : event_buffer_flush(struct event_buffer *bufp, uint8_t dev_id, uint8_t port_id,
     574                 :            :                    uint16_t *nb_events_flushed,
     575                 :            :                    uint16_t *nb_events_inv)
     576                 :            : {
     577                 :          0 :         struct rte_event *events = bufp->events;
     578                 :            :         size_t head_idx, tail_idx;
     579                 :            :         uint16_t n = 0;
     580                 :            : 
     581                 :            :         /* Instead of modulus, bitwise AND with mask to get index. */
     582                 :          0 :         head_idx = bufp->head & EVENT_BUFFER_MASK;
     583                 :          0 :         tail_idx = bufp->tail & EVENT_BUFFER_MASK;
     584                 :            : 
     585                 :            :         RTE_ASSERT(head_idx < EVENT_BUFFER_SZ && tail_idx < EVENT_BUFFER_SZ);
     586                 :            : 
     587                 :            :         /* Determine the largest contiguous run we can attempt to enqueue to the
     588                 :            :          * event device.
     589                 :            :          */
     590         [ #  # ]:          0 :         if (head_idx > tail_idx)
     591                 :          0 :                 n = head_idx - tail_idx;
     592         [ #  # ]:          0 :         else if (head_idx < tail_idx)
     593                 :          0 :                 n = EVENT_BUFFER_SZ - tail_idx;
     594         [ #  # ]:          0 :         else if (event_buffer_full(bufp))
     595                 :          0 :                 n = EVENT_BUFFER_SZ - tail_idx;
     596                 :            :         else {
     597                 :          0 :                 *nb_events_flushed = 0;
     598                 :          0 :                 return;
     599                 :            :         }
     600                 :            : 
     601                 :          0 :         n = RTE_MIN(EVENT_BUFFER_BATCHSZ, n);
     602                 :          0 :         *nb_events_inv = 0;
     603                 :            : 
     604                 :          0 :         *nb_events_flushed = rte_event_enqueue_burst(dev_id, port_id,
     605                 :          0 :                                                      &events[tail_idx], n);
     606         [ #  # ]:          0 :         if (*nb_events_flushed != n) {
     607         [ #  # ]:          0 :                 if (rte_errno == EINVAL) {
     608                 :          0 :                         EVTIM_LOG_ERR("failed to enqueue invalid event - "
     609                 :            :                                       "dropping it");
     610                 :          0 :                         (*nb_events_inv)++;
     611         [ #  # ]:          0 :                 } else if (rte_errno == ENOSPC)
     612                 :            :                         rte_pause();
     613                 :            :         }
     614                 :            : 
     615                 :          0 :         if (*nb_events_flushed > 0)
     616                 :            :                 EVTIM_BUF_LOG_DBG("enqueued %"PRIu16" timer events to event "
     617                 :            :                                   "device", *nb_events_flushed);
     618                 :            : 
     619                 :          0 :         bufp->tail = bufp->tail + *nb_events_flushed + *nb_events_inv;
     620                 :            : }
     621                 :            : 
     622                 :            : /*
     623                 :            :  * Software event timer adapter implementation
     624                 :            :  */
     625                 :            : struct swtim {
     626                 :            :         /* Identifier of service executing timer management logic. */
     627                 :            :         uint32_t service_id;
     628                 :            :         /* The cycle count at which the adapter should next tick */
     629                 :            :         uint64_t next_tick_cycles;
     630                 :            :         /* The tick resolution used by adapter instance. May have been
     631                 :            :          * adjusted from what user requested
     632                 :            :          */
     633                 :            :         uint64_t timer_tick_ns;
     634                 :            :         /* Maximum timeout in nanoseconds allowed by adapter instance. */
     635                 :            :         uint64_t max_tmo_ns;
     636                 :            :         /* Buffered timer expiry events to be enqueued to an event device. */
     637                 :            :         struct event_buffer buffer;
     638                 :            :         /* Statistics */
     639                 :            :         struct rte_event_timer_adapter_stats stats;
     640                 :            :         /* Mempool of timer objects */
     641                 :            :         struct rte_mempool *tim_pool;
     642                 :            :         /* Back pointer for convenience */
     643                 :            :         struct rte_event_timer_adapter *adapter;
     644                 :            :         /* Identifier of timer data instance */
     645                 :            :         uint32_t timer_data_id;
     646                 :            :         /* Track which cores have actually armed a timer */
     647                 :            :         alignas(RTE_CACHE_LINE_SIZE) struct {
     648                 :            :                 RTE_ATOMIC(uint16_t) v;
     649                 :            :         } in_use[RTE_MAX_LCORE];
     650                 :            :         /* Track which cores' timer lists should be polled */
     651                 :            :         RTE_ATOMIC(unsigned int) poll_lcores[RTE_MAX_LCORE];
     652                 :            :         /* The number of lists that should be polled */
     653                 :            :         RTE_ATOMIC(int) n_poll_lcores;
     654                 :            :         /* Timers which have expired and can be returned to a mempool */
     655                 :            :         struct rte_timer *expired_timers[EXP_TIM_BUF_SZ];
     656                 :            :         /* The number of timers that can be returned to a mempool */
     657                 :            :         size_t n_expired_timers;
     658                 :            : };
     659                 :            : 
     660                 :            : static inline struct swtim *
     661                 :            : swtim_pmd_priv(const struct rte_event_timer_adapter *adapter)
     662                 :            : {
     663                 :          0 :         return adapter->data->adapter_priv;
     664                 :            : }
     665                 :            : 
     666                 :            : static void
     667                 :          0 : swtim_callback(struct rte_timer *tim)
     668                 :            : {
     669         [ #  # ]:          0 :         struct rte_event_timer *evtim = tim->arg;
     670                 :            :         struct rte_event_timer_adapter *adapter;
     671                 :            :         unsigned int lcore = rte_lcore_id();
     672                 :            :         struct swtim *sw;
     673                 :          0 :         uint16_t nb_evs_flushed = 0;
     674                 :          0 :         uint16_t nb_evs_invalid = 0;
     675                 :            :         uint64_t opaque;
     676                 :            :         int ret;
     677                 :            :         int n_lcores;
     678                 :            :         enum rte_timer_type type;
     679                 :            : 
     680                 :          0 :         opaque = evtim->impl_opaque[1];
     681                 :          0 :         adapter = (struct rte_event_timer_adapter *)(uintptr_t)opaque;
     682                 :            :         sw = swtim_pmd_priv(adapter);
     683                 :            :         type = get_timer_type(adapter);
     684                 :            : 
     685         [ #  # ]:          0 :         if (unlikely(sw->in_use[lcore].v == 0)) {
     686                 :          0 :                 sw->in_use[lcore].v = 1;
     687                 :          0 :                 n_lcores = rte_atomic_fetch_add_explicit(&sw->n_poll_lcores, 1,
     688                 :            :                                              rte_memory_order_relaxed);
     689                 :          0 :                 rte_atomic_store_explicit(&sw->poll_lcores[n_lcores], lcore,
     690                 :            :                                 rte_memory_order_relaxed);
     691                 :            :         }
     692                 :            : 
     693         [ #  # ]:          0 :         ret = event_buffer_add(&sw->buffer, &evtim->ev);
     694                 :            :         if (ret < 0) {
     695         [ #  # ]:          0 :                 if (type == SINGLE) {
     696                 :            :                         /* If event buffer is full, put timer back in list with
     697                 :            :                          * immediate expiry value, so that we process it again
     698                 :            :                          * on the next iteration.
     699                 :            :                          */
     700                 :          0 :                         ret = rte_timer_alt_reset(sw->timer_data_id, tim, 0,
     701                 :            :                                                 SINGLE, lcore, NULL, evtim);
     702         [ #  # ]:          0 :                         if (ret < 0) {
     703                 :            :                                 EVTIM_LOG_DBG("event buffer full, failed to "
     704                 :            :                                                 "reset timer with immediate "
     705                 :            :                                                 "expiry value");
     706                 :            :                         } else {
     707                 :          0 :                                 sw->stats.evtim_retry_count++;
     708                 :            :                                 EVTIM_LOG_DBG("event buffer full, resetting "
     709                 :            :                                                 "rte_timer with immediate "
     710                 :            :                                                 "expiry value");
     711                 :            :                         }
     712                 :            :                 } else {
     713                 :          0 :                         sw->stats.evtim_drop_count++;
     714                 :            :                 }
     715                 :            : 
     716                 :            :         } else {
     717                 :            :                 EVTIM_BUF_LOG_DBG("buffered an event timer expiry event");
     718                 :            : 
     719                 :            :                 /* Empty the buffer here, if necessary, to free older expired
     720                 :            :                  * timers only
     721                 :            :                  */
     722         [ #  # ]:          0 :                 if (unlikely(sw->n_expired_timers == EXP_TIM_BUF_SZ)) {
     723                 :          0 :                         rte_mempool_put_bulk(sw->tim_pool,
     724         [ #  # ]:          0 :                                              (void **)sw->expired_timers,
     725                 :            :                                              sw->n_expired_timers);
     726                 :          0 :                         sw->n_expired_timers = 0;
     727                 :            :                 }
     728                 :            : 
     729                 :            :                 /* Don't free rte_timer for a periodic event timer until
     730                 :            :                  * it is cancelled
     731                 :            :                  */
     732         [ #  # ]:          0 :                 if (type == SINGLE)
     733                 :          0 :                         sw->expired_timers[sw->n_expired_timers++] = tim;
     734                 :          0 :                 sw->stats.evtim_exp_count++;
     735                 :            : 
     736         [ #  # ]:          0 :                 if (type == SINGLE)
     737                 :          0 :                         rte_atomic_store_explicit(&evtim->state, RTE_EVENT_TIMER_NOT_ARMED,
     738                 :            :                                 rte_memory_order_release);
     739                 :            :         }
     740                 :            : 
     741         [ #  # ]:          0 :         if (event_buffer_batch_ready(&sw->buffer)) {
     742                 :          0 :                 event_buffer_flush(&sw->buffer,
     743                 :          0 :                                    adapter->data->event_dev_id,
     744                 :          0 :                                    adapter->data->event_port_id,
     745                 :            :                                    &nb_evs_flushed,
     746                 :            :                                    &nb_evs_invalid);
     747                 :            : 
     748                 :          0 :                 sw->stats.ev_enq_count += nb_evs_flushed;
     749                 :          0 :                 sw->stats.ev_inv_count += nb_evs_invalid;
     750                 :            :         }
     751                 :          0 : }
     752                 :            : 
     753                 :            : static __rte_always_inline int
     754                 :            : get_timeout_cycles(struct rte_event_timer *evtim,
     755                 :            :                    const struct rte_event_timer_adapter *adapter,
     756                 :            :                    uint64_t *timeout_cycles)
     757                 :            : {
     758                 :            :         static struct rte_reciprocal_u64 nsecpersec_inverse;
     759                 :            :         static uint64_t timer_hz;
     760                 :            :         uint64_t rem_cycles, secs_cycles = 0;
     761                 :            :         uint64_t secs, timeout_nsecs;
     762                 :            :         uint64_t nsecpersec;
     763                 :            :         struct swtim *sw;
     764                 :            : 
     765                 :            :         sw = swtim_pmd_priv(adapter);
     766                 :            :         nsecpersec = (uint64_t)NSECPERSEC;
     767                 :            : 
     768                 :          0 :         timeout_nsecs = evtim->timeout_ticks * sw->timer_tick_ns;
     769                 :          0 :         if (timeout_nsecs > sw->max_tmo_ns)
     770                 :            :                 return -1;
     771         [ #  # ]:          0 :         if (timeout_nsecs < sw->timer_tick_ns)
     772                 :            :                 return -2;
     773                 :            : 
     774                 :            :         /* Set these values in the first invocation */
     775         [ #  # ]:          0 :         if (!timer_hz) {
     776                 :          0 :                 timer_hz = rte_get_timer_hz();
     777                 :          0 :                 nsecpersec_inverse = rte_reciprocal_value_u64(nsecpersec);
     778                 :            :         }
     779                 :            : 
     780                 :            :         /* If timeout_nsecs > nsecpersec, decrease timeout_nsecs by the number
     781                 :            :          * of whole seconds it contains and convert that value to a number
     782                 :            :          * of cycles. This keeps timeout_nsecs in the interval [0..nsecpersec)
     783                 :            :          * in order to avoid overflow when we later multiply by timer_hz.
     784                 :            :          */
     785         [ #  # ]:          0 :         if (timeout_nsecs > nsecpersec) {
     786                 :            :                 secs = rte_reciprocal_divide_u64(timeout_nsecs,
     787                 :            :                                                  &nsecpersec_inverse);
     788                 :          0 :                 secs_cycles = secs * timer_hz;
     789                 :          0 :                 timeout_nsecs -= secs * nsecpersec;
     790                 :            :         }
     791                 :            : 
     792                 :          0 :         rem_cycles = rte_reciprocal_divide_u64(timeout_nsecs * timer_hz,
     793                 :            :                                                &nsecpersec_inverse);
     794                 :            : 
     795                 :          0 :         *timeout_cycles = secs_cycles + rem_cycles;
     796                 :            : 
     797                 :          0 :         return 0;
     798                 :            : }
     799                 :            : 
     800                 :            : /* This function returns true if one or more (adapter) ticks have occurred since
     801                 :            :  * the last time it was called.
     802                 :            :  */
     803                 :            : static inline bool
     804                 :          0 : swtim_did_tick(struct swtim *sw)
     805                 :            : {
     806                 :            :         uint64_t cycles_per_adapter_tick, start_cycles;
     807                 :            :         uint64_t *next_tick_cyclesp;
     808                 :            : 
     809                 :            :         next_tick_cyclesp = &sw->next_tick_cycles;
     810                 :          0 :         cycles_per_adapter_tick = sw->timer_tick_ns *
     811                 :          0 :                         (rte_get_timer_hz() / NSECPERSEC);
     812                 :            :         start_cycles = rte_get_timer_cycles();
     813                 :            : 
     814                 :            :         /* Note: initially, *next_tick_cyclesp == 0, so the clause below will
     815                 :            :          * execute, and set things going.
     816                 :            :          */
     817                 :            : 
     818         [ #  # ]:          0 :         if (start_cycles >= *next_tick_cyclesp) {
     819                 :            :                 /* Snap the current cycle count to the preceding adapter tick
     820                 :            :                  * boundary.
     821                 :            :                  */
     822                 :          0 :                 start_cycles -= start_cycles % cycles_per_adapter_tick;
     823                 :          0 :                 *next_tick_cyclesp = start_cycles + cycles_per_adapter_tick;
     824                 :            : 
     825                 :          0 :                 return true;
     826                 :            :         }
     827                 :            : 
     828                 :            :         return false;
     829                 :            : }
     830                 :            : 
     831                 :            : /* Check that event timer event queue sched type matches destination event queue
     832                 :            :  * sched type
     833                 :            :  */
     834                 :            : static __rte_always_inline int
     835                 :            : check_destination_event_queue(struct rte_event_timer *evtim,
     836                 :            :                               const struct rte_event_timer_adapter *adapter)
     837                 :            : {
     838                 :            :         int ret;
     839                 :            :         uint32_t sched_type;
     840                 :            : 
     841                 :          0 :         ret = rte_event_queue_attr_get(adapter->data->event_dev_id,
     842                 :          0 :                                        evtim->ev.queue_id,
     843                 :            :                                        RTE_EVENT_QUEUE_ATTR_SCHEDULE_TYPE,
     844                 :            :                                        &sched_type);
     845                 :            : 
     846   [ #  #  #  #  :          0 :         if ((ret == 0 && evtim->ev.sched_type == sched_type) ||
                   #  # ]
     847                 :            :             ret == -EOVERFLOW)
     848                 :          0 :                 return 0;
     849                 :            : 
     850                 :            :         return -1;
     851                 :            : }
     852                 :            : 
     853                 :            : static int
     854                 :          0 : swtim_service_func(void *arg)
     855                 :            : {
     856                 :            :         struct rte_event_timer_adapter *adapter = arg;
     857                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
     858                 :          0 :         uint16_t nb_evs_flushed = 0;
     859                 :          0 :         uint16_t nb_evs_invalid = 0;
     860                 :          0 :         const uint64_t prior_enq_count = sw->stats.ev_enq_count;
     861                 :            : 
     862         [ #  # ]:          0 :         if (swtim_did_tick(sw)) {
     863                 :          0 :                 rte_timer_alt_manage(sw->timer_data_id,
     864                 :          0 :                                      (unsigned int *)(uintptr_t)sw->poll_lcores,
     865                 :            :                                      sw->n_poll_lcores,
     866                 :            :                                      swtim_callback);
     867                 :            : 
     868                 :            :                 /* Return expired timer objects back to mempool */
     869                 :          0 :                 rte_mempool_put_bulk(sw->tim_pool, (void **)sw->expired_timers,
     870         [ #  # ]:          0 :                                      sw->n_expired_timers);
     871                 :          0 :                 sw->n_expired_timers = 0;
     872                 :            : 
     873                 :          0 :                 sw->stats.adapter_tick_count++;
     874                 :            :         }
     875                 :            : 
     876                 :          0 :         event_buffer_flush(&sw->buffer,
     877                 :          0 :                            adapter->data->event_dev_id,
     878                 :          0 :                            adapter->data->event_port_id,
     879                 :            :                            &nb_evs_flushed,
     880                 :            :                            &nb_evs_invalid);
     881                 :            : 
     882                 :          0 :         sw->stats.ev_enq_count += nb_evs_flushed;
     883                 :          0 :         sw->stats.ev_inv_count += nb_evs_invalid;
     884                 :            : 
     885                 :          0 :         rte_event_maintain(adapter->data->event_dev_id,
     886         [ #  # ]:          0 :                            adapter->data->event_port_id, 0);
     887                 :            : 
     888         [ #  # ]:          0 :         return prior_enq_count == sw->stats.ev_enq_count ? -EAGAIN : 0;
     889                 :            : }
     890                 :            : 
     891                 :            : /* The adapter initialization function rounds the mempool size up to the next
     892                 :            :  * power of 2, so we can take the difference between that value and what the
     893                 :            :  * user requested, and use the space for caches.  This avoids a scenario where a
     894                 :            :  * user can't arm the number of timers the adapter was configured with because
     895                 :            :  * mempool objects have been lost to caches.
     896                 :            :  *
     897                 :            :  * nb_actual should always be a power of 2, so we can iterate over the powers
     898                 :            :  * of 2 to see what the largest cache size we can use is.
     899                 :            :  */
     900                 :            : static int
     901                 :            : compute_msg_mempool_cache_size(uint64_t nb_requested, uint64_t nb_actual)
     902                 :            : {
     903                 :            :         int i;
     904                 :            :         int size;
     905                 :            :         int cache_size = 0;
     906                 :            : 
     907                 :          0 :         for (i = 0;; i++) {
     908                 :          0 :                 size = 1 << i;
     909                 :            : 
     910   [ #  #  #  # ]:          0 :                 if (RTE_MAX_LCORE * size < (int)(nb_actual - nb_requested) &&
     911                 :          0 :                     size < RTE_MEMPOOL_CACHE_MAX_SIZE &&
     912         [ #  # ]:          0 :                     size <= nb_actual / 1.5)
     913                 :            :                         cache_size = size;
     914                 :            :                 else
     915                 :            :                         break;
     916                 :            :         }
     917                 :            : 
     918                 :            :         return cache_size;
     919                 :            : }
     920                 :            : 
     921                 :            : static int
     922                 :          0 : swtim_init(struct rte_event_timer_adapter *adapter)
     923                 :            : {
     924                 :            :         int i, ret;
     925                 :            :         struct swtim *sw;
     926                 :            :         unsigned int flags;
     927                 :            :         struct rte_service_spec service;
     928                 :            : 
     929                 :            :         /* Allocate storage for private data area */
     930                 :            : #define SWTIM_NAMESIZE 32
     931                 :            :         char swtim_name[SWTIM_NAMESIZE];
     932                 :          0 :         snprintf(swtim_name, SWTIM_NAMESIZE, "swtim_%"PRIu8,
     933                 :          0 :                         adapter->data->id);
     934                 :          0 :         sw = rte_zmalloc_socket(swtim_name, sizeof(*sw), RTE_CACHE_LINE_SIZE,
     935                 :          0 :                         adapter->data->socket_id);
     936         [ #  # ]:          0 :         if (sw == NULL) {
     937                 :          0 :                 EVTIM_LOG_ERR("failed to allocate space for private data");
     938                 :          0 :                 rte_errno = ENOMEM;
     939                 :          0 :                 return -1;
     940                 :            :         }
     941                 :            : 
     942                 :            :         /* Connect storage to adapter instance */
     943                 :          0 :         adapter->data->adapter_priv = sw;
     944                 :          0 :         sw->adapter = adapter;
     945                 :            : 
     946                 :          0 :         sw->timer_tick_ns = adapter->data->conf.timer_tick_ns;
     947                 :          0 :         sw->max_tmo_ns = adapter->data->conf.max_tmo_ns;
     948                 :            : 
     949                 :            :         /* Create a timer pool */
     950                 :            :         char pool_name[SWTIM_NAMESIZE];
     951                 :          0 :         snprintf(pool_name, SWTIM_NAMESIZE, "swtim_pool_%"PRIu8,
     952                 :          0 :                  adapter->data->id);
     953                 :            :         /* Optimal mempool size is a power of 2 minus one */
     954                 :          0 :         uint64_t nb_timers = rte_align64pow2(adapter->data->conf.nb_timers);
     955                 :          0 :         int pool_size = nb_timers - 1;
     956                 :            :         int cache_size = compute_msg_mempool_cache_size(
     957                 :            :                                 adapter->data->conf.nb_timers, nb_timers);
     958                 :            :         flags = 0; /* pool is multi-producer, multi-consumer */
     959                 :          0 :         sw->tim_pool = rte_mempool_create(pool_name, pool_size,
     960                 :            :                         sizeof(struct rte_timer), cache_size, 0, NULL, NULL,
     961                 :          0 :                         NULL, NULL, adapter->data->socket_id, flags);
     962         [ #  # ]:          0 :         if (sw->tim_pool == NULL) {
     963                 :          0 :                 EVTIM_LOG_ERR("failed to create timer object mempool");
     964                 :          0 :                 rte_errno = ENOMEM;
     965                 :          0 :                 goto free_alloc;
     966                 :            :         }
     967                 :            : 
     968                 :            :         /* Initialize the variables that track in-use timer lists */
     969         [ #  # ]:          0 :         for (i = 0; i < RTE_MAX_LCORE; i++)
     970                 :          0 :                 sw->in_use[i].v = 0;
     971                 :            : 
     972                 :            :         /* Initialize the timer subsystem and allocate timer data instance */
     973                 :          0 :         ret = rte_timer_subsystem_init();
     974         [ #  # ]:          0 :         if (ret < 0) {
     975         [ #  # ]:          0 :                 if (ret != -EALREADY) {
     976                 :          0 :                         EVTIM_LOG_ERR("failed to initialize timer subsystem");
     977                 :          0 :                         rte_errno = -ret;
     978                 :          0 :                         goto free_mempool;
     979                 :            :                 }
     980                 :            :         }
     981                 :            : 
     982                 :          0 :         ret = rte_timer_data_alloc(&sw->timer_data_id);
     983         [ #  # ]:          0 :         if (ret < 0) {
     984                 :          0 :                 EVTIM_LOG_ERR("failed to allocate timer data instance");
     985                 :          0 :                 rte_errno = -ret;
     986                 :          0 :                 goto free_mempool;
     987                 :            :         }
     988                 :            : 
     989                 :            :         /* Initialize timer event buffer */
     990                 :            :         event_buffer_init(&sw->buffer);
     991                 :            : 
     992                 :          0 :         sw->adapter = adapter;
     993                 :            : 
     994                 :            :         /* Register a service component to run adapter logic */
     995                 :            :         memset(&service, 0, sizeof(service));
     996                 :          0 :         snprintf(service.name, RTE_SERVICE_NAME_MAX,
     997                 :          0 :                  "swtim_svc_%"PRIu8, adapter->data->id);
     998                 :          0 :         service.socket_id = adapter->data->socket_id;
     999                 :          0 :         service.callback = swtim_service_func;
    1000                 :          0 :         service.callback_userdata = adapter;
    1001                 :          0 :         service.capabilities &= ~(RTE_SERVICE_CAP_MT_SAFE);
    1002                 :          0 :         ret = rte_service_component_register(&service, &sw->service_id);
    1003         [ #  # ]:          0 :         if (ret < 0) {
    1004                 :          0 :                 EVTIM_LOG_ERR("failed to register service %s with id %"PRIu32
    1005                 :            :                               ": err = %d", service.name, sw->service_id,
    1006                 :            :                               ret);
    1007                 :            : 
    1008                 :          0 :                 rte_errno = ENOSPC;
    1009                 :          0 :                 goto free_mempool;
    1010                 :            :         }
    1011                 :            : 
    1012                 :            :         EVTIM_LOG_DBG("registered service %s with id %"PRIu32, service.name,
    1013                 :            :                       sw->service_id);
    1014                 :            : 
    1015                 :          0 :         adapter->data->service_id = sw->service_id;
    1016                 :          0 :         adapter->data->service_inited = 1;
    1017                 :            : 
    1018                 :          0 :         return 0;
    1019                 :          0 : free_mempool:
    1020                 :          0 :         rte_mempool_free(sw->tim_pool);
    1021                 :          0 : free_alloc:
    1022                 :          0 :         rte_free(sw);
    1023                 :          0 :         return -1;
    1024                 :            : }
    1025                 :            : 
    1026                 :            : static void
    1027                 :          0 : swtim_free_tim(struct rte_timer *tim, void *arg)
    1028                 :            : {
    1029                 :            :         struct swtim *sw = arg;
    1030                 :            : 
    1031         [ #  # ]:          0 :         rte_mempool_put(sw->tim_pool, tim);
    1032                 :          0 : }
    1033                 :            : 
    1034                 :            : /* Traverse the list of outstanding timers and put them back in the mempool
    1035                 :            :  * before freeing the adapter to avoid leaking the memory.
    1036                 :            :  */
    1037                 :            : static int
    1038                 :          0 : swtim_uninit(struct rte_event_timer_adapter *adapter)
    1039                 :            : {
    1040                 :            :         int ret;
    1041                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1042                 :            : 
    1043                 :            :         /* Free outstanding timers */
    1044                 :          0 :         rte_timer_stop_all(sw->timer_data_id,
    1045                 :          0 :                            (unsigned int *)(uintptr_t)sw->poll_lcores,
    1046                 :            :                            sw->n_poll_lcores,
    1047                 :            :                            swtim_free_tim,
    1048                 :            :                            sw);
    1049                 :            : 
    1050                 :          0 :         ret = rte_timer_data_dealloc(sw->timer_data_id);
    1051         [ #  # ]:          0 :         if (ret < 0) {
    1052                 :          0 :                 EVTIM_LOG_ERR("failed to deallocate timer data instance");
    1053                 :          0 :                 return ret;
    1054                 :            :         }
    1055                 :            : 
    1056                 :          0 :         ret = rte_service_component_unregister(sw->service_id);
    1057         [ #  # ]:          0 :         if (ret < 0) {
    1058                 :          0 :                 EVTIM_LOG_ERR("failed to unregister service component");
    1059                 :          0 :                 return ret;
    1060                 :            :         }
    1061                 :            : 
    1062                 :          0 :         rte_mempool_free(sw->tim_pool);
    1063                 :          0 :         rte_free(sw);
    1064                 :          0 :         adapter->data->adapter_priv = NULL;
    1065                 :            : 
    1066                 :          0 :         return 0;
    1067                 :            : }
    1068                 :            : 
    1069                 :            : static inline int32_t
    1070                 :          0 : get_mapped_count_for_service(uint32_t service_id)
    1071                 :            : {
    1072                 :            :         int32_t core_count, i, mapped_count = 0;
    1073                 :            :         uint32_t lcore_arr[RTE_MAX_LCORE];
    1074                 :            : 
    1075                 :          0 :         core_count = rte_service_lcore_list(lcore_arr, RTE_MAX_LCORE);
    1076                 :            : 
    1077         [ #  # ]:          0 :         for (i = 0; i < core_count; i++)
    1078         [ #  # ]:          0 :                 if (rte_service_map_lcore_get(service_id, lcore_arr[i]) == 1)
    1079                 :          0 :                         mapped_count++;
    1080                 :            : 
    1081                 :          0 :         return mapped_count;
    1082                 :            : }
    1083                 :            : 
    1084                 :            : static int
    1085                 :          0 : swtim_start(const struct rte_event_timer_adapter *adapter)
    1086                 :            : {
    1087                 :            :         int mapped_count;
    1088                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1089                 :            : 
    1090                 :            :         /* Mapping the service to more than one service core can introduce
    1091                 :            :          * delays while one thread is waiting to acquire a lock, so only allow
    1092                 :            :          * one core to be mapped to the service.
    1093                 :            :          *
    1094                 :            :          * Note: the service could be modified such that it spreads cores to
    1095                 :            :          * poll over multiple service instances.
    1096                 :            :          */
    1097                 :          0 :         mapped_count = get_mapped_count_for_service(sw->service_id);
    1098                 :            : 
    1099         [ #  # ]:          0 :         if (mapped_count != 1)
    1100         [ #  # ]:          0 :                 return mapped_count < 1 ? -ENOENT : -ENOTSUP;
    1101                 :            : 
    1102                 :          0 :         return rte_service_component_runstate_set(sw->service_id, 1);
    1103                 :            : }
    1104                 :            : 
    1105                 :            : static int
    1106                 :          0 : swtim_stop(const struct rte_event_timer_adapter *adapter)
    1107                 :            : {
    1108                 :            :         int ret;
    1109                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1110                 :            : 
    1111                 :          0 :         ret = rte_service_component_runstate_set(sw->service_id, 0);
    1112         [ #  # ]:          0 :         if (ret < 0)
    1113                 :            :                 return ret;
    1114                 :            : 
    1115                 :            :         /* Wait for the service to complete its final iteration */
    1116         [ #  # ]:          0 :         while (rte_service_may_be_active(sw->service_id))
    1117                 :            :                 rte_pause();
    1118                 :            : 
    1119                 :            :         return 0;
    1120                 :            : }
    1121                 :            : 
    1122                 :            : static void
    1123                 :          0 : swtim_get_info(const struct rte_event_timer_adapter *adapter,
    1124                 :            :                 struct rte_event_timer_adapter_info *adapter_info)
    1125                 :            : {
    1126                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1127                 :          0 :         adapter_info->min_resolution_ns = sw->timer_tick_ns;
    1128                 :          0 :         adapter_info->max_tmo_ns = sw->max_tmo_ns;
    1129                 :          0 : }
    1130                 :            : 
    1131                 :            : static int
    1132                 :          0 : swtim_stats_get(const struct rte_event_timer_adapter *adapter,
    1133                 :            :                 struct rte_event_timer_adapter_stats *stats)
    1134                 :            : {
    1135                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1136                 :          0 :         *stats = sw->stats; /* structure copy */
    1137                 :          0 :         return 0;
    1138                 :            : }
    1139                 :            : 
    1140                 :            : static int
    1141                 :          0 : swtim_stats_reset(const struct rte_event_timer_adapter *adapter)
    1142                 :            : {
    1143                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1144                 :          0 :         memset(&sw->stats, 0, sizeof(sw->stats));
    1145                 :          0 :         return 0;
    1146                 :            : }
    1147                 :            : 
    1148                 :            : static int
    1149                 :          0 : swtim_remaining_ticks_get(const struct rte_event_timer_adapter *adapter,
    1150                 :            :                           const struct rte_event_timer *evtim,
    1151                 :            :                           uint64_t *ticks_remaining)
    1152                 :            : {
    1153                 :            :         uint64_t nsecs_per_adapter_tick, opaque, cycles_remaining;
    1154                 :            :         enum rte_event_timer_state n_state;
    1155                 :            :         double nsecs_per_cycle;
    1156                 :            :         struct rte_timer *tim;
    1157                 :            :         uint64_t cur_cycles;
    1158                 :            : 
    1159                 :            :         /* Check that timer is armed */
    1160                 :          0 :         n_state = rte_atomic_load_explicit(&evtim->state, rte_memory_order_acquire);
    1161         [ #  # ]:          0 :         if (n_state != RTE_EVENT_TIMER_ARMED)
    1162                 :            :                 return -EINVAL;
    1163                 :            : 
    1164                 :          0 :         opaque = evtim->impl_opaque[0];
    1165                 :          0 :         tim = (struct rte_timer *)(uintptr_t)opaque;
    1166                 :            : 
    1167                 :            :         cur_cycles = rte_get_timer_cycles();
    1168         [ #  # ]:          0 :         if (cur_cycles > tim->expire) {
    1169                 :          0 :                 *ticks_remaining = 0;
    1170                 :          0 :                 return 0;
    1171                 :            :         }
    1172                 :            : 
    1173                 :          0 :         cycles_remaining = tim->expire - cur_cycles;
    1174                 :          0 :         nsecs_per_cycle = (double)NSECPERSEC / rte_get_timer_hz();
    1175                 :          0 :         nsecs_per_adapter_tick = adapter->data->conf.timer_tick_ns;
    1176                 :            : 
    1177                 :          0 :         *ticks_remaining = (uint64_t)ceil((cycles_remaining * nsecs_per_cycle) /
    1178                 :            :                                           nsecs_per_adapter_tick);
    1179                 :            : 
    1180                 :          0 :         return 0;
    1181                 :            : }
    1182                 :            : 
    1183                 :            : static uint16_t
    1184                 :          0 : __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
    1185                 :            :                 struct rte_event_timer **evtims,
    1186                 :            :                 uint16_t nb_evtims)
    1187         [ #  # ]:          0 : {
    1188                 :            :         int i, ret;
    1189                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1190                 :            :         uint32_t lcore_id = rte_lcore_id();
    1191                 :          0 :         struct rte_timer *tim, *tims[nb_evtims];
    1192                 :            :         uint64_t cycles;
    1193                 :            :         int n_lcores;
    1194                 :            :         /* Timer list for this lcore is not in use. */
    1195                 :            :         uint16_t exp_state = 0;
    1196                 :            :         enum rte_event_timer_state n_state;
    1197                 :            :         enum rte_timer_type type = SINGLE;
    1198                 :            : 
    1199                 :            : #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
    1200                 :            :         /* Check that the service is running. */
    1201                 :            :         if (rte_service_runstate_get(adapter->data->service_id) != 1) {
    1202                 :            :                 rte_errno = EINVAL;
    1203                 :            :                 return 0;
    1204                 :            :         }
    1205                 :            : #endif
    1206                 :            : 
    1207                 :            :         /* Adjust lcore_id if non-EAL thread. Arbitrarily pick the timer list of
    1208                 :            :          * the highest lcore to insert such timers into
    1209                 :            :          */
    1210         [ #  # ]:          0 :         if (lcore_id == LCORE_ID_ANY)
    1211                 :            :                 lcore_id = RTE_MAX_LCORE - 1;
    1212                 :            : 
    1213                 :            :         /* If this is the first time we're arming an event timer on this lcore,
    1214                 :            :          * mark this lcore as "in use"; this will cause the service
    1215                 :            :          * function to process the timer list that corresponds to this lcore.
    1216                 :            :          * The atomic compare-and-swap operation can prevent the race condition
    1217                 :            :          * on in_use flag between multiple non-EAL threads.
    1218                 :            :          */
    1219         [ #  # ]:          0 :         if (unlikely(rte_atomic_compare_exchange_strong_explicit(&sw->in_use[lcore_id].v,
    1220                 :            :                         &exp_state, 1,
    1221                 :            :                         rte_memory_order_relaxed, rte_memory_order_relaxed))) {
    1222                 :            :                 EVTIM_LOG_DBG("Adding lcore id = %u to list of lcores to poll",
    1223                 :            :                               lcore_id);
    1224                 :          0 :                 n_lcores = rte_atomic_fetch_add_explicit(&sw->n_poll_lcores, 1,
    1225                 :            :                                              rte_memory_order_relaxed);
    1226                 :          0 :                 rte_atomic_store_explicit(&sw->poll_lcores[n_lcores], lcore_id,
    1227                 :            :                                 rte_memory_order_relaxed);
    1228                 :            :         }
    1229                 :            : 
    1230         [ #  # ]:          0 :         ret = rte_mempool_get_bulk(sw->tim_pool, (void **)tims,
    1231                 :            :                                    nb_evtims);
    1232         [ #  # ]:          0 :         if (ret < 0) {
    1233                 :          0 :                 rte_errno = ENOSPC;
    1234                 :          0 :                 return 0;
    1235                 :            :         }
    1236                 :            : 
    1237                 :            :         /* update timer type for periodic adapter */
    1238                 :            :         type = get_timer_type(adapter);
    1239                 :            : 
    1240         [ #  # ]:          0 :         for (i = 0; i < nb_evtims; i++) {
    1241                 :          0 :                 n_state = rte_atomic_load_explicit(&evtims[i]->state, rte_memory_order_acquire);
    1242         [ #  # ]:          0 :                 if (n_state == RTE_EVENT_TIMER_ARMED) {
    1243                 :          0 :                         rte_errno = EALREADY;
    1244                 :          0 :                         break;
    1245                 :          0 :                 } else if (!(n_state == RTE_EVENT_TIMER_NOT_ARMED ||
    1246         [ #  # ]:          0 :                              n_state == RTE_EVENT_TIMER_CANCELED)) {
    1247                 :          0 :                         rte_errno = EINVAL;
    1248                 :          0 :                         break;
    1249                 :            :                 }
    1250                 :            : 
    1251         [ #  # ]:          0 :                 if (unlikely(check_destination_event_queue(evtims[i],
    1252                 :            :                                                            adapter) < 0)) {
    1253                 :          0 :                         rte_atomic_store_explicit(&evtims[i]->state,
    1254                 :            :                                         RTE_EVENT_TIMER_ERROR,
    1255                 :            :                                         rte_memory_order_relaxed);
    1256                 :          0 :                         rte_errno = EINVAL;
    1257                 :          0 :                         break;
    1258                 :            :                 }
    1259                 :            : 
    1260                 :          0 :                 tim = tims[i];
    1261                 :          0 :                 rte_timer_init(tim);
    1262                 :            : 
    1263                 :          0 :                 evtims[i]->impl_opaque[0] = (uintptr_t)tim;
    1264         [ #  # ]:          0 :                 evtims[i]->impl_opaque[1] = (uintptr_t)adapter;
    1265                 :            : 
    1266                 :            :                 ret = get_timeout_cycles(evtims[i], adapter, &cycles);
    1267         [ #  # ]:          0 :                 if (unlikely(ret == -1)) {
    1268                 :          0 :                         rte_atomic_store_explicit(&evtims[i]->state,
    1269                 :            :                                         RTE_EVENT_TIMER_ERROR_TOOLATE,
    1270                 :            :                                         rte_memory_order_relaxed);
    1271                 :          0 :                         rte_errno = EINVAL;
    1272                 :          0 :                         break;
    1273         [ #  # ]:          0 :                 } else if (unlikely(ret == -2)) {
    1274                 :          0 :                         rte_atomic_store_explicit(&evtims[i]->state,
    1275                 :            :                                         RTE_EVENT_TIMER_ERROR_TOOEARLY,
    1276                 :            :                                         rte_memory_order_relaxed);
    1277                 :          0 :                         rte_errno = EINVAL;
    1278                 :          0 :                         break;
    1279                 :            :                 }
    1280                 :            : 
    1281                 :          0 :                 ret = rte_timer_alt_reset(sw->timer_data_id, tim, cycles,
    1282                 :            :                                           type, lcore_id, NULL, evtims[i]);
    1283         [ #  # ]:          0 :                 if (ret < 0) {
    1284                 :            :                         /* tim was in RUNNING or CONFIG state */
    1285                 :          0 :                         rte_atomic_store_explicit(&evtims[i]->state,
    1286                 :            :                                         RTE_EVENT_TIMER_ERROR,
    1287                 :            :                                         rte_memory_order_release);
    1288                 :          0 :                         break;
    1289                 :            :                 }
    1290                 :            : 
    1291                 :            :                 EVTIM_LOG_DBG("armed an event timer");
    1292                 :            :                 /* RELEASE ordering guarantees the adapter specific value
    1293                 :            :                  * changes observed before the update of state.
    1294                 :            :                  */
    1295                 :          0 :                 rte_atomic_store_explicit(&evtims[i]->state, RTE_EVENT_TIMER_ARMED,
    1296                 :            :                                 rte_memory_order_release);
    1297                 :            :         }
    1298                 :            : 
    1299         [ #  # ]:          0 :         if (i < nb_evtims)
    1300                 :          0 :                 rte_mempool_put_bulk(sw->tim_pool,
    1301         [ #  # ]:          0 :                                      (void **)&tims[i], nb_evtims - i);
    1302                 :            : 
    1303                 :          0 :         return i;
    1304                 :            : }
    1305                 :            : 
    1306                 :            : static uint16_t
    1307                 :          0 : swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
    1308                 :            :                 struct rte_event_timer **evtims,
    1309                 :            :                 uint16_t nb_evtims)
    1310                 :            : {
    1311                 :          0 :         return __swtim_arm_burst(adapter, evtims, nb_evtims);
    1312                 :            : }
    1313                 :            : 
    1314                 :            : static uint16_t
    1315                 :          0 : swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
    1316                 :            :                    struct rte_event_timer **evtims,
    1317                 :            :                    uint16_t nb_evtims)
    1318                 :            : {
    1319                 :            :         int i, ret;
    1320                 :            :         struct rte_timer *timp;
    1321                 :            :         uint64_t opaque;
    1322                 :            :         struct swtim *sw = swtim_pmd_priv(adapter);
    1323                 :            :         enum rte_event_timer_state n_state;
    1324                 :            : 
    1325                 :            : #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
    1326                 :            :         /* Check that the service is running. */
    1327                 :            :         if (rte_service_runstate_get(adapter->data->service_id) != 1) {
    1328                 :            :                 rte_errno = EINVAL;
    1329                 :            :                 return 0;
    1330                 :            :         }
    1331                 :            : #endif
    1332                 :            : 
    1333         [ #  # ]:          0 :         for (i = 0; i < nb_evtims; i++) {
    1334                 :            :                 /* Don't modify the event timer state in these cases */
    1335                 :            :                 /* ACQUIRE ordering guarantees the access of implementation
    1336                 :            :                  * specific opaque data under the correct state.
    1337                 :            :                  */
    1338                 :          0 :                 n_state = rte_atomic_load_explicit(&evtims[i]->state, rte_memory_order_acquire);
    1339         [ #  # ]:          0 :                 if (n_state == RTE_EVENT_TIMER_CANCELED) {
    1340                 :          0 :                         rte_errno = EALREADY;
    1341                 :          0 :                         break;
    1342         [ #  # ]:          0 :                 } else if (n_state != RTE_EVENT_TIMER_ARMED) {
    1343                 :          0 :                         rte_errno = EINVAL;
    1344                 :          0 :                         break;
    1345                 :            :                 }
    1346                 :            : 
    1347                 :          0 :                 opaque = evtims[i]->impl_opaque[0];
    1348                 :          0 :                 timp = (struct rte_timer *)(uintptr_t)opaque;
    1349                 :            :                 RTE_ASSERT(timp != NULL);
    1350                 :            : 
    1351                 :          0 :                 ret = rte_timer_alt_stop(sw->timer_data_id, timp);
    1352         [ #  # ]:          0 :                 if (ret < 0) {
    1353                 :            :                         /* Timer is running or being configured */
    1354                 :          0 :                         rte_errno = EAGAIN;
    1355                 :          0 :                         break;
    1356                 :            :                 }
    1357                 :            : 
    1358         [ #  # ]:          0 :                 rte_mempool_put(sw->tim_pool, (void **)timp);
    1359                 :            : 
    1360                 :            :                 /* The RELEASE ordering here pairs with atomic ordering
    1361                 :            :                  * to make sure the state update data observed between
    1362                 :            :                  * threads.
    1363                 :            :                  */
    1364                 :          0 :                 rte_atomic_store_explicit(&evtims[i]->state, RTE_EVENT_TIMER_CANCELED,
    1365                 :            :                                 rte_memory_order_release);
    1366                 :            :         }
    1367                 :            : 
    1368                 :          0 :         return i;
    1369                 :            : }
    1370                 :            : 
    1371                 :            : static uint16_t
    1372                 :          0 : swtim_arm_tmo_tick_burst(const struct rte_event_timer_adapter *adapter,
    1373                 :            :                          struct rte_event_timer **evtims,
    1374                 :            :                          uint64_t timeout_ticks,
    1375                 :            :                          uint16_t nb_evtims)
    1376                 :            : {
    1377                 :            :         int i;
    1378                 :            : 
    1379         [ #  # ]:          0 :         for (i = 0; i < nb_evtims; i++)
    1380                 :          0 :                 evtims[i]->timeout_ticks = timeout_ticks;
    1381                 :            : 
    1382                 :          0 :         return __swtim_arm_burst(adapter, evtims, nb_evtims);
    1383                 :            : }
    1384                 :            : 
    1385                 :            : static const struct event_timer_adapter_ops swtim_ops = {
    1386                 :            :         .init = swtim_init,
    1387                 :            :         .uninit = swtim_uninit,
    1388                 :            :         .start = swtim_start,
    1389                 :            :         .stop = swtim_stop,
    1390                 :            :         .get_info = swtim_get_info,
    1391                 :            :         .stats_get = swtim_stats_get,
    1392                 :            :         .stats_reset = swtim_stats_reset,
    1393                 :            :         .arm_burst = swtim_arm_burst,
    1394                 :            :         .arm_tmo_tick_burst = swtim_arm_tmo_tick_burst,
    1395                 :            :         .cancel_burst = swtim_cancel_burst,
    1396                 :            :         .remaining_ticks_get = swtim_remaining_ticks_get,
    1397                 :            : };
    1398                 :            : 
    1399                 :            : static int
    1400                 :          0 : handle_ta_info(const char *cmd __rte_unused, const char *params,
    1401                 :            :                 struct rte_tel_data *d)
    1402                 :            : {
    1403                 :            :         struct rte_event_timer_adapter_info adapter_info;
    1404                 :            :         struct rte_event_timer_adapter *adapter;
    1405                 :            :         uint16_t adapter_id;
    1406                 :            :         int ret;
    1407                 :            : 
    1408   [ #  #  #  #  :          0 :         if (params == NULL || strlen(params) == 0 || !isdigit(*params))
                   #  # ]
    1409                 :            :                 return -1;
    1410                 :            : 
    1411                 :          0 :         adapter_id = atoi(params);
    1412                 :            : 
    1413         [ #  # ]:          0 :         if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
    1414                 :          0 :                 EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
    1415                 :          0 :                 return -EINVAL;
    1416                 :            :         }
    1417                 :            : 
    1418                 :          0 :         adapter = &adapters[adapter_id];
    1419                 :            : 
    1420                 :          0 :         ret = rte_event_timer_adapter_get_info(adapter, &adapter_info);
    1421         [ #  # ]:          0 :         if (ret < 0) {
    1422                 :          0 :                 EVTIM_LOG_ERR("Failed to get info for timer adapter id %u", adapter_id);
    1423                 :          0 :                 return ret;
    1424                 :            :         }
    1425                 :            : 
    1426                 :          0 :         rte_tel_data_start_dict(d);
    1427                 :          0 :         rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
    1428                 :          0 :         rte_tel_data_add_dict_uint(d, "min_resolution_ns",
    1429                 :            :                                    adapter_info.min_resolution_ns);
    1430                 :          0 :         rte_tel_data_add_dict_uint(d, "max_tmo_ns", adapter_info.max_tmo_ns);
    1431                 :          0 :         rte_tel_data_add_dict_uint(d, "event_dev_id",
    1432                 :          0 :                                    adapter_info.conf.event_dev_id);
    1433                 :          0 :         rte_tel_data_add_dict_uint(d, "socket_id",
    1434                 :          0 :                                    adapter_info.conf.socket_id);
    1435                 :          0 :         rte_tel_data_add_dict_uint(d, "clk_src", adapter_info.conf.clk_src);
    1436                 :          0 :         rte_tel_data_add_dict_uint(d, "timer_tick_ns",
    1437                 :            :                                    adapter_info.conf.timer_tick_ns);
    1438                 :          0 :         rte_tel_data_add_dict_uint(d, "nb_timers",
    1439                 :            :                                    adapter_info.conf.nb_timers);
    1440                 :          0 :         rte_tel_data_add_dict_uint(d, "flags", adapter_info.conf.flags);
    1441                 :            : 
    1442                 :          0 :         return 0;
    1443                 :            : }
    1444                 :            : 
    1445                 :            : static int
    1446                 :          0 : handle_ta_stats(const char *cmd __rte_unused, const char *params,
    1447                 :            :                 struct rte_tel_data *d)
    1448                 :            : {
    1449                 :            :         struct rte_event_timer_adapter_stats stats;
    1450                 :            :         struct rte_event_timer_adapter *adapter;
    1451                 :            :         uint16_t adapter_id;
    1452                 :            :         int ret;
    1453                 :            : 
    1454   [ #  #  #  #  :          0 :         if (params == NULL || strlen(params) == 0 || !isdigit(*params))
                   #  # ]
    1455                 :            :                 return -1;
    1456                 :            : 
    1457                 :          0 :         adapter_id = atoi(params);
    1458                 :            : 
    1459         [ #  # ]:          0 :         if (adapter_id >= RTE_EVENT_TIMER_ADAPTER_NUM_MAX) {
    1460                 :          0 :                 EVTIM_LOG_ERR("Invalid timer adapter id %u", adapter_id);
    1461                 :          0 :                 return -EINVAL;
    1462                 :            :         }
    1463                 :            : 
    1464                 :          0 :         adapter = &adapters[adapter_id];
    1465                 :            : 
    1466                 :          0 :         ret = rte_event_timer_adapter_stats_get(adapter, &stats);
    1467         [ #  # ]:          0 :         if (ret < 0) {
    1468                 :          0 :                 EVTIM_LOG_ERR("Failed to get stats for timer adapter id %u", adapter_id);
    1469                 :          0 :                 return ret;
    1470                 :            :         }
    1471                 :            : 
    1472                 :          0 :         rte_tel_data_start_dict(d);
    1473                 :          0 :         rte_tel_data_add_dict_uint(d, "timer_adapter_id", adapter_id);
    1474                 :          0 :         rte_tel_data_add_dict_uint(d, "evtim_exp_count",
    1475                 :            :                                    stats.evtim_exp_count);
    1476                 :          0 :         rte_tel_data_add_dict_uint(d, "ev_enq_count", stats.ev_enq_count);
    1477                 :          0 :         rte_tel_data_add_dict_uint(d, "ev_inv_count", stats.ev_inv_count);
    1478                 :          0 :         rte_tel_data_add_dict_uint(d, "evtim_retry_count",
    1479                 :            :                                    stats.evtim_retry_count);
    1480                 :          0 :         rte_tel_data_add_dict_uint(d, "adapter_tick_count",
    1481                 :            :                                    stats.adapter_tick_count);
    1482                 :            : 
    1483                 :          0 :         return 0;
    1484                 :            : }
    1485                 :            : 
    1486                 :        252 : RTE_INIT(ta_init_telemetry)
    1487                 :            : {
    1488                 :        252 :         rte_telemetry_register_cmd("/eventdev/ta_info",
    1489                 :            :                 handle_ta_info,
    1490                 :            :                 "Returns Timer adapter info. Parameter: Timer adapter id");
    1491                 :            : 
    1492                 :        252 :         rte_telemetry_register_cmd("/eventdev/ta_stats",
    1493                 :            :                 handle_ta_stats,
    1494                 :            :                 "Returns Timer adapter stats. Parameter: Timer adapter id");
    1495                 :        252 : }

Generated by: LCOV version 1.14