This patch adds support to configure and use periodic event
timers in software timer adapter.

The structure ``rte_event_timer_adapter_stats`` is extended
by adding a new field, ``evtim_drop_count``. This stat
represents the number of times an event_timer expiry event
is dropped by the event timer adapter.

Signed-off-by: Naga Harish K S V <s.v.naga.haris...@intel.com>
---
 lib/eventdev/rte_event_timer_adapter.c | 86 ++++++++++++++++++--------
 lib/eventdev/rte_event_timer_adapter.h |  2 +
 lib/eventdev/rte_eventdev.c            |  6 +-
 3 files changed, 67 insertions(+), 27 deletions(-)

diff --git a/lib/eventdev/rte_event_timer_adapter.c 
b/lib/eventdev/rte_event_timer_adapter.c
index e0d978d641..f96cb98b5b 100644
--- a/lib/eventdev/rte_event_timer_adapter.c
+++ b/lib/eventdev/rte_event_timer_adapter.c
@@ -53,6 +53,14 @@ static const struct event_timer_adapter_ops swtim_ops;
 #define EVTIM_SVC_LOG_DBG(...) (void)0
 #endif
 
+static inline enum rte_timer_type
+get_event_timer_type(const struct rte_event_timer_adapter *adapter)
+{
+       return (adapter->data->conf.flags &
+                       RTE_EVENT_TIMER_ADAPTER_F_PERIODIC) ?
+                       PERIODICAL : SINGLE;
+}
+
 static int
 default_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id,
                     void *conf_arg)
@@ -195,10 +203,11 @@ rte_event_timer_adapter_create_ext(
        adapter->data->conf = *conf;  /* copy conf structure */
 
        /* Query eventdev PMD for timer adapter capabilities and ops */
-       ret = dev->dev_ops->timer_adapter_caps_get(dev,
+       ret = dev->dev_ops->timer_adapter_caps_get ?
+                               dev->dev_ops->timer_adapter_caps_get(dev,
                                                   adapter->data->conf.flags,
                                                   &adapter->data->caps,
-                                                  &adapter->ops);
+                                                  &adapter->ops) : 0;
        if (ret < 0) {
                rte_errno = -ret;
                goto free_memzone;
@@ -348,10 +357,11 @@ rte_event_timer_adapter_lookup(uint16_t adapter_id)
        dev = &rte_eventdevs[adapter->data->event_dev_id];
 
        /* Query eventdev PMD for timer adapter capabilities and ops */
-       ret = dev->dev_ops->timer_adapter_caps_get(dev,
+       ret = dev->dev_ops->timer_adapter_caps_get ?
+                       dev->dev_ops->timer_adapter_caps_get(dev,
                                                   adapter->data->conf.flags,
                                                   &adapter->data->caps,
-                                                  &adapter->ops);
+                                                  &adapter->ops) : 0;
        if (ret < 0) {
                rte_errno = EINVAL;
                return NULL;
@@ -612,35 +622,44 @@ swtim_callback(struct rte_timer *tim)
        uint64_t opaque;
        int ret;
        int n_lcores;
+       enum rte_timer_type type;
 
        opaque = evtim->impl_opaque[1];
        adapter = (struct rte_event_timer_adapter *)(uintptr_t)opaque;
        sw = swtim_pmd_priv(adapter);
+       type = get_event_timer_type(adapter);
+
+       if (unlikely(sw->in_use[lcore].v == 0)) {
+               sw->in_use[lcore].v = 1;
+               n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
+                                            __ATOMIC_RELAXED);
+               __atomic_store_n(&sw->poll_lcores[n_lcores], lcore,
+                               __ATOMIC_RELAXED);
+       }
 
        ret = event_buffer_add(&sw->buffer, &evtim->ev);
        if (ret < 0) {
-               /* If event buffer is full, put timer back in list with
-                * immediate expiry value, so that we process it again on the
-                * next iteration.
-                */
-               ret = rte_timer_alt_reset(sw->timer_data_id, tim, 0, SINGLE,
-                                         lcore, NULL, evtim);
-               if (ret < 0) {
-                       EVTIM_LOG_DBG("event buffer full, failed to reset "
-                                     "timer with immediate expiry value");
+               if (type == SINGLE) {
+                       /* If event buffer is full, put timer back in list with
+                       * immediate expiry value, so that we process it again
+                       * on the next iteration.
+                       */
+                       ret = rte_timer_alt_reset(sw->timer_data_id, tim, 0,
+                                               SINGLE, lcore, NULL, evtim);
+                       if (ret < 0) {
+                               EVTIM_LOG_DBG("event buffer full, failed to "
+                                               "reset timer with immediate "
+                                               "expiry value");
+                       } else {
+                               sw->stats.evtim_retry_count++;
+                               EVTIM_LOG_DBG("event buffer full, resetting "
+                                               "rte_timer with immediate "
+                                               "expiry value");
+                       }
                } else {
-                       sw->stats.evtim_retry_count++;
-                       EVTIM_LOG_DBG("event buffer full, resetting rte_timer "
-                                     "with immediate expiry value");
+                       sw->stats.evtim_drop_count++;
                }
 
-               if (unlikely(sw->in_use[lcore].v == 0)) {
-                       sw->in_use[lcore].v = 1;
-                       n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
-                                                    __ATOMIC_RELAXED);
-                       __atomic_store_n(&sw->poll_lcores[n_lcores], lcore,
-                                       __ATOMIC_RELAXED);
-               }
        } else {
                EVTIM_BUF_LOG_DBG("buffered an event timer expiry event");
 
@@ -654,10 +673,15 @@ swtim_callback(struct rte_timer *tim)
                        sw->n_expired_timers = 0;
                }
 
-               sw->expired_timers[sw->n_expired_timers++] = tim;
+               /* Don't free rte_timer for a periodic event timer until
+                * it is cancelled
+                */
+               if (type == SINGLE)
+                       sw->expired_timers[sw->n_expired_timers++] = tim;
                sw->stats.evtim_exp_count++;
 
-               __atomic_store_n(&evtim->state, RTE_EVENT_TIMER_NOT_ARMED,
+               if (type == SINGLE)
+                       __atomic_store_n(&evtim->state, 
RTE_EVENT_TIMER_NOT_ARMED,
                                __ATOMIC_RELEASE);
        }
 
@@ -947,6 +971,12 @@ swtim_uninit(struct rte_event_timer_adapter *adapter)
                           swtim_free_tim,
                           sw);
 
+       ret = rte_timer_data_dealloc(sw->timer_data_id);
+       if (ret < 0) {
+               EVTIM_LOG_ERR("failed to deallocate timer data instance");
+               return ret;
+       }
+
        ret = rte_service_component_unregister(sw->service_id);
        if (ret < 0) {
                EVTIM_LOG_ERR("failed to unregister service component");
@@ -1053,6 +1083,7 @@ __swtim_arm_burst(const struct rte_event_timer_adapter 
*adapter,
        /* Timer list for this lcore is not in use. */
        uint16_t exp_state = 0;
        enum rte_event_timer_state n_state;
+       enum rte_timer_type type = SINGLE;
 
 #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
        /* Check that the service is running. */
@@ -1092,6 +1123,9 @@ __swtim_arm_burst(const struct rte_event_timer_adapter 
*adapter,
                return 0;
        }
 
+       /* update timer type for periodic adapter */
+       type = get_event_timer_type(adapter);
+
        for (i = 0; i < nb_evtims; i++) {
                n_state = __atomic_load_n(&evtims[i]->state, __ATOMIC_ACQUIRE);
                if (n_state == RTE_EVENT_TIMER_ARMED) {
@@ -1135,7 +1169,7 @@ __swtim_arm_burst(const struct rte_event_timer_adapter 
*adapter,
 
                cycles = get_timeout_cycles(evtims[i], adapter);
                ret = rte_timer_alt_reset(sw->timer_data_id, tim, cycles,
-                                         SINGLE, lcore_id, NULL, evtims[i]);
+                                         type, lcore_id, NULL, evtims[i]);
                if (ret < 0) {
                        /* tim was in RUNNING or CONFIG state */
                        __atomic_store_n(&evtims[i]->state,
diff --git a/lib/eventdev/rte_event_timer_adapter.h 
b/lib/eventdev/rte_event_timer_adapter.h
index eab8e59a57..cd10db19e4 100644
--- a/lib/eventdev/rte_event_timer_adapter.h
+++ b/lib/eventdev/rte_event_timer_adapter.h
@@ -193,6 +193,8 @@ struct rte_event_timer_adapter_stats {
        /**< Event timer retry count */
        uint64_t adapter_tick_count;
        /**< Tick count for the adapter, at its resolution */
+       uint64_t evtim_drop_count;
+       /**< event timer expiries dropped */
 };
 
 struct rte_event_timer_adapter;
diff --git a/lib/eventdev/rte_eventdev.c b/lib/eventdev/rte_eventdev.c
index 1dc4f966be..4a2a1178da 100644
--- a/lib/eventdev/rte_eventdev.c
+++ b/lib/eventdev/rte_eventdev.c
@@ -139,7 +139,11 @@ rte_event_timer_adapter_caps_get(uint8_t dev_id, uint32_t 
*caps)
 
        if (caps == NULL)
                return -EINVAL;
-       *caps = 0;
+
+       if (dev->dev_ops->timer_adapter_caps_get == NULL)
+               *caps = RTE_EVENT_TIMER_ADAPTER_CAP_PERIODIC;
+       else
+               *caps = 0;
 
        return dev->dev_ops->timer_adapter_caps_get ?
                                (*dev->dev_ops->timer_adapter_caps_get)(dev,
-- 
2.25.1

Reply via email to