eventdev/timer: support periodic event timer
Add 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. Updated the software eventdev pmd timer_adapter_caps_get callback function to report the support of periodic event timer capability. Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com> Acked-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
This commit is contained in:
parent
f089d62895
commit
3d9d8adf8c
@ -386,11 +386,22 @@ timdev_setup_msec(void)
|
||||
static int
|
||||
timdev_setup_msec_periodic(void)
|
||||
{
|
||||
uint32_t caps = 0;
|
||||
uint64_t max_tmo_ns;
|
||||
|
||||
uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES |
|
||||
RTE_EVENT_TIMER_ADAPTER_F_PERIODIC;
|
||||
|
||||
TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
|
||||
"failed to get adapter capabilities");
|
||||
|
||||
if (caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)
|
||||
max_tmo_ns = 0;
|
||||
else
|
||||
max_tmo_ns = 180 * NSECPERSEC;
|
||||
|
||||
/* Periodic mode with 100 ms resolution */
|
||||
return _timdev_setup(0, NSECPERSEC / 10, flags);
|
||||
return _timdev_setup(max_tmo_ns, NSECPERSEC / 10, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -409,7 +420,7 @@ timdev_setup_sec_periodic(void)
|
||||
RTE_EVENT_TIMER_ADAPTER_F_PERIODIC;
|
||||
|
||||
/* Periodic mode with 1 sec resolution */
|
||||
return _timdev_setup(0, NSECPERSEC, flags);
|
||||
return _timdev_setup(180 * NSECPERSEC, NSECPERSEC, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -561,12 +572,23 @@ test_timer_arm(void)
|
||||
static inline int
|
||||
test_timer_arm_periodic(void)
|
||||
{
|
||||
uint32_t caps = 0;
|
||||
uint32_t timeout_count = 0;
|
||||
|
||||
TEST_ASSERT_SUCCESS(_arm_timers(1, MAX_TIMERS),
|
||||
"Failed to arm timers");
|
||||
/* With a resolution of 100ms and wait time of 1sec,
|
||||
* there will be 10 * MAX_TIMERS periodic timer triggers.
|
||||
*/
|
||||
TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, 10 * MAX_TIMERS, 0),
|
||||
TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
|
||||
"failed to get adapter capabilities");
|
||||
|
||||
if (caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)
|
||||
timeout_count = 10;
|
||||
else
|
||||
timeout_count = 9;
|
||||
|
||||
TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, timeout_count * MAX_TIMERS, 0),
|
||||
"Timer triggered count doesn't match arm count");
|
||||
return TEST_SUCCESS;
|
||||
}
|
||||
@ -649,12 +671,23 @@ test_timer_arm_burst(void)
|
||||
static inline int
|
||||
test_timer_arm_burst_periodic(void)
|
||||
{
|
||||
uint32_t caps = 0;
|
||||
uint32_t timeout_count = 0;
|
||||
|
||||
TEST_ASSERT_SUCCESS(_arm_timers_burst(1, MAX_TIMERS),
|
||||
"Failed to arm timers");
|
||||
/* With a resolution of 100ms and wait time of 1sec,
|
||||
* there will be 10 * MAX_TIMERS periodic timer triggers.
|
||||
*/
|
||||
TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, 10 * MAX_TIMERS, 0),
|
||||
TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
|
||||
"failed to get adapter capabilities");
|
||||
|
||||
if (caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)
|
||||
timeout_count = 10;
|
||||
else
|
||||
timeout_count = 9;
|
||||
|
||||
TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, timeout_count * MAX_TIMERS, 0),
|
||||
"Timer triggered count doesn't match arm count");
|
||||
|
||||
return TEST_SUCCESS;
|
||||
|
@ -162,13 +162,6 @@ Deprecation Notices
|
||||
Event will be one of the configuration fields,
|
||||
together with additional vector parameters.
|
||||
|
||||
* eventdev: The structure ``rte_event_timer_adapter_stats`` will be
|
||||
extended by adding a new field ``evtim_drop_count``.
|
||||
This counter will represent the number of times an event_timer expiry event
|
||||
is dropped by the timer adapter.
|
||||
This field will be used to add periodic mode support
|
||||
to the software timer adapter in DPDK 22.11.
|
||||
|
||||
* eventdev: The function pointer declaration ``eventdev_stop_flush_t``
|
||||
will be renamed to ``rte_eventdev_stop_flush_t`` in DPDK 22.11.
|
||||
|
||||
|
@ -234,6 +234,9 @@ ABI Changes
|
||||
|
||||
* ethdev: enum ``RTE_FLOW_ACTION`` was affected by deprecation procedure.
|
||||
|
||||
* eventdev: Added ``evtim_drop_count`` field
|
||||
to ``rte_event_timer_adapter_stats`` structure.
|
||||
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
@ -565,7 +565,7 @@ sw_timer_adapter_caps_get(const struct rte_eventdev *dev, uint64_t flags,
|
||||
{
|
||||
RTE_SET_USED(dev);
|
||||
RTE_SET_USED(flags);
|
||||
*caps = 0;
|
||||
*caps = RTE_EVENT_TIMER_ADAPTER_SW_CAP;
|
||||
|
||||
/* Use default SW ops */
|
||||
*ops = NULL;
|
||||
|
@ -81,6 +81,9 @@ extern "C" {
|
||||
* the ethdev to eventdev use a SW service function
|
||||
*/
|
||||
|
||||
#define RTE_EVENT_TIMER_ADAPTER_SW_CAP \
|
||||
RTE_EVENT_TIMER_ADAPTER_CAP_PERIODIC
|
||||
|
||||
#define RTE_EVENTDEV_DETACHED (0)
|
||||
#define RTE_EVENTDEV_ATTACHED (1)
|
||||
|
||||
|
@ -55,6 +55,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_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)
|
||||
@ -197,13 +205,14 @@ 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,
|
||||
adapter->data->conf.flags,
|
||||
&adapter->data->caps,
|
||||
&adapter->ops);
|
||||
if (ret < 0) {
|
||||
rte_errno = -ret;
|
||||
goto free_memzone;
|
||||
if (dev->dev_ops->timer_adapter_caps_get) {
|
||||
ret = dev->dev_ops->timer_adapter_caps_get(dev,
|
||||
adapter->data->conf.flags,
|
||||
&adapter->data->caps, &adapter->ops);
|
||||
if (ret < 0) {
|
||||
rte_errno = -ret;
|
||||
goto free_memzone;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(adapter->data->caps &
|
||||
@ -350,13 +359,14 @@ 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,
|
||||
adapter->data->conf.flags,
|
||||
&adapter->data->caps,
|
||||
&adapter->ops);
|
||||
if (ret < 0) {
|
||||
rte_errno = EINVAL;
|
||||
return NULL;
|
||||
if (dev->dev_ops->timer_adapter_caps_get) {
|
||||
ret = dev->dev_ops->timer_adapter_caps_get(dev,
|
||||
adapter->data->conf.flags,
|
||||
&adapter->data->caps, &adapter->ops);
|
||||
if (ret < 0) {
|
||||
rte_errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If eventdev PMD did not provide ops, use default software
|
||||
@ -614,35 +624,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_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");
|
||||
|
||||
@ -656,10 +675,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);
|
||||
}
|
||||
|
||||
@ -949,6 +973,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");
|
||||
@ -1055,6 +1085,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. */
|
||||
@ -1094,6 +1125,9 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update timer type for periodic adapter */
|
||||
type = get_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) {
|
||||
@ -1137,7 +1171,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,
|
||||
|
@ -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;
|
||||
|
@ -140,7 +140,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_SW_CAP;
|
||||
else
|
||||
*caps = 0;
|
||||
|
||||
return dev->dev_ops->timer_adapter_caps_get ?
|
||||
(*dev->dev_ops->timer_adapter_caps_get)(dev,
|
||||
|
Loading…
Reference in New Issue
Block a user