From patchwork Mon Nov 20 22:35:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Carrillo, Erik G" X-Patchwork-Id: 31489 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 563777CD8; Mon, 20 Nov 2017 23:35:31 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 8155C7CD6 for ; Mon, 20 Nov 2017 23:35:29 +0100 (CET) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Nov 2017 14:35:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,430,1505804400"; d="scan'208";a="4069285" Received: from wcpqa1.an.intel.com ([10.123.72.207]) by fmsmga004.fm.intel.com with ESMTP; 20 Nov 2017 14:35:26 -0800 From: Erik Gabriel Carrillo To: jerin.jacob@caviumnetworks.com Cc: dev@dpdk.org, pbhagavatula@caviumnetworks.com, nipun.gupta@nxp.com, hemant.agrawal@nxp.com, nikhil.rao@intel.com, narender.vangati@intel.com, rsanford@akamai.com Date: Mon, 20 Nov 2017 16:35:33 -0600 Message-Id: <1511217333-142455-2-git-send-email-erik.g.carrillo@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1511217333-142455-1-git-send-email-erik.g.carrillo@intel.com> References: <1506093431-57588-1-git-send-email-erik.g.carrillo@intel.com> <1511217333-142455-1-git-send-email-erik.g.carrillo@intel.com> Subject: [dpdk-dev] [RFC PATCH v3 1/1] eventtimer: introduce event timer adapter X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: Erik Gabriel Carrillo --- v3 - Reworked allocation and ops organization in common code based on feedback received from Jerin and Pavan. This will allow fast-path function pointers to be dereferenced with one level of indirection with pointers valid in primary and secondary processes. - Moved default software implementation from sw_evdev directory to eventdev library directory, which will allow it to be used by any eventdev PMD as an alternative to providing its own definitions. - Reverted occurrences of id back to pointer to adapter struct in library API - Added rte_event_timer_adapter_lookup() function back in v2 - Added ops structure and stubbed out plugin for SW impl - Added unit test stubs - Replaced occurrences of "wheel" in API with "adapter" - Replaced occurrences of pointer to struct rte_event_timer_adapter with ids - Removed rte_event_timer_adapter_lookup() function - Replaced RTE_EVENT_TIMER_SUCCESS_{ARM,CANCEL} states with RTE_EVENT_TIMER_ARMED doc/api/doxy-api-index.md | 1 + drivers/event/sw/sw_evdev.c | 16 + lib/librte_eventdev/Makefile | 4 + lib/librte_eventdev/rte_event_timer_adapter.c | 428 +++++++++++++++++++++ lib/librte_eventdev/rte_event_timer_adapter.h | 427 ++++++++++++++++++++ .../rte_event_timer_adapter_driver.h | 159 ++++++++ lib/librte_eventdev/rte_eventdev.h | 3 + lib/librte_eventdev/rte_eventdev_pmd.h | 7 + lib/librte_eventdev/rte_eventdev_version.map | 15 +- lib/librte_eventdev/sw_event_timer_adapter.c | 123 ++++++ test/test/Makefile | 1 + test/test/test_event_timer_adapter.c | 249 ++++++++++++ 12 files changed, 1432 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eventdev/rte_event_timer_adapter.c create mode 100644 lib/librte_eventdev/rte_event_timer_adapter.h create mode 100644 lib/librte_eventdev/rte_event_timer_adapter_driver.h create mode 100644 lib/librte_eventdev/sw_event_timer_adapter.c create mode 100644 test/test/test_event_timer_adapter.c diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 3492702..3110658 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -46,6 +46,7 @@ The public API headers are grouped by topics: [security] (@ref rte_security.h), [eventdev] (@ref rte_eventdev.h), [event_eth_rx_adapter] (@ref rte_event_eth_rx_adapter.h), + [event_timer_adapter] (@ref rte_event_timer_adapter.h), [metrics] (@ref rte_metrics.h), [bitrate] (@ref rte_bitrate.h), [latency] (@ref rte_latencystats.h), diff --git a/drivers/event/sw/sw_evdev.c b/drivers/event/sw/sw_evdev.c index fd11079..cba8c8c 100644 --- a/drivers/event/sw/sw_evdev.c +++ b/drivers/event/sw/sw_evdev.c @@ -435,6 +435,20 @@ sw_eth_rx_adapter_caps_get(const struct rte_eventdev *dev, return 0; } +static int +sw_timer_adapter_caps_get(const struct rte_eventdev *dev, + uint32_t *caps, + const struct rte_event_timer_adapter_ops **ops) +{ + RTE_SET_USED(dev); + *caps = 0; + + /* Use default SW ops */ + *ops = NULL; + + return 0; +} + static void sw_info_get(struct rte_eventdev *dev, struct rte_event_dev_info *info) { @@ -755,6 +769,8 @@ sw_probe(struct rte_vdev_device *vdev) .eth_rx_adapter_caps_get = sw_eth_rx_adapter_caps_get, + .timer_adapter_caps_get = sw_timer_adapter_caps_get, + .xstats_get = sw_xstats_get, .xstats_get_names = sw_xstats_get_names, .xstats_get_by_name = sw_xstats_get_by_name, diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile index 5ac22cd..d5c7cc7 100644 --- a/lib/librte_eventdev/Makefile +++ b/lib/librte_eventdev/Makefile @@ -45,6 +45,8 @@ LDLIBS += -lrte_eal -lrte_ring -lrte_ethdev -lrte_hash SRCS-y += rte_eventdev.c SRCS-y += rte_event_ring.c SRCS-y += rte_event_eth_rx_adapter.c +SRCS-y += rte_event_timer_adapter.c +SRCS-y += sw_event_timer_adapter.c # export include files SYMLINK-y-include += rte_eventdev.h @@ -53,6 +55,8 @@ SYMLINK-y-include += rte_eventdev_pmd_pci.h SYMLINK-y-include += rte_eventdev_pmd_vdev.h SYMLINK-y-include += rte_event_ring.h SYMLINK-y-include += rte_event_eth_rx_adapter.h +SYMLINK-y-include += rte_event_timer_adapter.h +SYMLINK-y-include += rte_event_timer_adapter_driver.h # versioning export map EXPORT_MAP := rte_eventdev_version.map diff --git a/lib/librte_eventdev/rte_event_timer_adapter.c b/lib/librte_eventdev/rte_event_timer_adapter.c new file mode 100644 index 0000000..09dcf0f --- /dev/null +++ b/lib/librte_eventdev/rte_event_timer_adapter.c @@ -0,0 +1,428 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include + +#include "rte_eventdev.h" +#include "rte_eventdev_pmd.h" +#include "rte_event_timer_adapter.h" +#include "rte_event_timer_adapter_driver.h" + +#define MAX_EVENT_TIMER_ADAPTERS 64 +#define DATA_MZ_NAME_MAX_LEN 64 +#define DATA_MZ_NAME_FORMAT "rte_event_timer_adapter_data_%d" + +static struct rte_event_timer_adapter adapters[MAX_EVENT_TIMER_ADAPTERS]; + +extern const struct rte_event_timer_adapter_ops sw_event_adapter_timer_ops; + +static inline int +adapter_valid(const struct rte_event_timer_adapter *adapter) +{ + return adapter != NULL && adapter->allocated == 1; +} + +#define ADAPTER_VALID_OR_ERR_RET(adapter, retval) do { \ + if (!adapter_valid(adapter)) \ + return retval; \ +} while (0) + +#define FUNC_PTR_OR_ERR_RET(func, errval) do { \ + if ((func) == NULL) \ + return errval; \ +} while (0) + +#define FUNC_PTR_OR_NULL_RET_WITH_ERRNO(func, errval) do { \ + if ((func) == NULL) { \ + rte_errno = errval; \ + return NULL; \ + } \ +} while (0) + +static int +default_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id, + void *conf_arg) +{ + struct rte_event_timer_adapter *adapter; + struct rte_eventdev *dev; + struct rte_event_dev_config dev_conf; + struct rte_event_port_conf *port_conf = conf_arg; + int started; + uint8_t port_id; + uint8_t dev_id; + int ret; + + RTE_SET_USED(event_dev_id); + + adapter = &adapters[id]; + dev = &rte_eventdevs[adapter->data->event_dev_id]; + dev_id = dev->data->dev_id; + dev_conf = dev->data->dev_conf; + + started = dev->data->dev_started; + if (started) + rte_event_dev_stop(dev_id); + + port_id = dev_conf.nb_event_ports; + dev_conf.nb_event_ports += 1; + ret = rte_event_dev_configure(dev_id, &dev_conf); + if (ret < 0) { + if (started) + rte_event_dev_start(dev_id); + + return ret; + } + + ret = rte_event_port_setup(dev_id, port_id, port_conf); + if (ret < 0) + return ret; + + *event_port_id = port_id; + + if (started) + rte_event_dev_start(dev_id); + + return 0; +} + +struct rte_event_timer_adapter * +rte_event_timer_adapter_create(const struct rte_event_timer_adapter_conf *conf) +{ + /* default port conf values */ + struct rte_event_port_conf port_conf = { + .new_event_threshold = 128, + .dequeue_depth = 32, + .enqueue_depth = 32 + }; + + return rte_event_timer_adapter_create_ext(conf, default_port_conf_cb, + &port_conf); +} + +struct rte_event_timer_adapter * +rte_event_timer_adapter_create_ext( + const struct rte_event_timer_adapter_conf *conf, + rte_event_timer_adapter_port_conf_cb_t conf_cb, + void *conf_arg) +{ + uint16_t adapter_id; + struct rte_event_timer_adapter *adapter; + const struct rte_memzone *mz; + char mz_name[DATA_MZ_NAME_MAX_LEN]; + int n, ret; + struct rte_eventdev *dev; + + if (conf == NULL) { + rte_errno = -EINVAL; + return NULL; + } + + /* Check eventdev ID */ + if (!rte_event_pmd_is_valid_dev(conf->event_dev_id)) { + rte_errno = -EINVAL; + return NULL; + } + dev = &rte_eventdevs[conf->event_dev_id]; + + adapter_id = conf->timer_adapter_id; + + /* Check adapter ID not already allocated */ + adapter = &adapters[adapter_id]; + if (adapter->allocated) { + rte_errno = -EEXIST; + return NULL; + } + + /* Create shared data area. */ + n = snprintf(mz_name, sizeof(mz_name), DATA_MZ_NAME_FORMAT, adapter_id); + if (n >= (int)sizeof(mz_name)) { + rte_errno = -EINVAL; + return NULL; + } + mz = rte_memzone_reserve(mz_name, + sizeof(struct rte_event_timer_adapter_data), + conf->socket_id, 0); + if (mz == NULL) + /* rte_errno set by rte_memzone_reserve */ + return NULL; + + adapter->data = mz->addr; + memset(adapter->data, 0, sizeof(struct rte_event_timer_adapter_data)); + + adapter->data->mz = mz; + adapter->data->event_dev_id = conf->event_dev_id; + adapter->data->id = adapter_id; + adapter->data->socket_id = conf->socket_id; + 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->caps, + &adapter->ops); + if (ret < 0) { + rte_errno = -EINVAL; + return NULL; + } + + if (!(adapter->data->caps & + RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) { + FUNC_PTR_OR_NULL_RET_WITH_ERRNO(conf_cb, -EINVAL); + ret = conf_cb(adapter->data->id, adapter->data->event_dev_id, + &adapter->data->event_port_id, conf_arg); + if (ret < 0) { + rte_errno = -EINVAL; + return NULL; + } + } + + /* If eventdev PMD did not provide ops, use default software + * implementation. + */ + if (adapter->ops == NULL) + adapter->ops = &sw_event_adapter_timer_ops; + + /* Allow driver to do some setup */ + FUNC_PTR_OR_NULL_RET_WITH_ERRNO(adapter->ops->init, -ENOTSUP); + ret = adapter->ops->init(adapter); + if (ret < 0) { + rte_errno = -EINVAL; + return NULL; + } + + /* Set fast-path function pointers */ + adapter->arm_burst = adapter->ops->arm_burst; + adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst; + adapter->cancel_burst = adapter->ops->cancel_burst; + + adapter->allocated = 1; + + return adapter; +} + +int +rte_event_timer_adapter_get_info(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer_adapter_info *adapter_info) +{ + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + + if (adapter->ops->get_info) + /* let driver set values it knows */ + adapter->ops->get_info(adapter, adapter_info); + + /* Set common values */ + adapter_info->conf = adapter->data->conf; + adapter_info->event_dev_port_id = adapter->data->event_port_id; + adapter_info->caps = adapter->data->caps; + + return 0; +} + +int +rte_event_timer_adapter_start(const struct rte_event_timer_adapter *adapter) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->ops->start, -EINVAL); + + ret = adapter->ops->start(adapter); + if (ret < 0) + return ret; + + adapter->data->started = 1; + + return 0; +} + +int +rte_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->ops->stop, -EINVAL); + + ret = adapter->ops->stop(adapter); + if (ret < 0) + return ret; + + adapter->data->started = 0; + + return 0; +} + +struct rte_event_timer_adapter * +rte_event_timer_adapter_lookup(uint16_t adapter_id) +{ + char name[DATA_MZ_NAME_MAX_LEN]; + const struct rte_memzone *mz; + struct rte_event_timer_adapter_data *data; + struct rte_event_timer_adapter *adapter; + int ret; + struct rte_eventdev *dev; + + if (adapters[adapter_id].allocated) + return &adapters[adapter_id]; /* Adapter is already loaded */ + + snprintf(name, DATA_MZ_NAME_MAX_LEN, DATA_MZ_NAME_FORMAT, adapter_id); + mz = rte_memzone_lookup(name); + if (mz == NULL) { + rte_errno = -ENOENT; + return NULL; + } + + data = mz->addr; + + adapter = &adapters[data->id]; + adapter->data = data; + + 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->caps, + &adapter->ops); + if (ret < 0) { + rte_errno = -EINVAL; + return NULL; + } + + /* If eventdev PMD did not provide ops, use default software + * implementation. + */ + if (adapter->ops == NULL) + adapter->ops = &sw_event_adapter_timer_ops; + + /* Set fast-path function pointers */ + adapter->arm_burst = adapter->ops->arm_burst; + adapter->arm_tmo_tick_burst = adapter->ops->arm_tmo_tick_burst; + adapter->cancel_burst = adapter->ops->cancel_burst; + + adapter->allocated = 1; + + return adapter; +} + +int +rte_event_timer_adapter_free(struct rte_event_timer_adapter *adapter) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->ops->uninit, -EINVAL); + + /* free impl priv data */ + ret = adapter->ops->uninit(adapter); + if (ret < 0) + return ret; + + /* free shared data area */ + ret = rte_memzone_free(adapter->data->mz); + if (ret < 0) + return ret; + + adapter->data = NULL; + adapter->allocated = 0; + + return 0; +} + +int +rte_event_timer_arm_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + uint16_t nb_event_timers) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->arm_burst, -EINVAL); + + if (!adapter->data->started) + return -EAGAIN; + + ret = adapter->arm_burst(adapter, event_timers, nb_event_timers); + if (ret < 0) + return ret; + + return 0; +} + +int +rte_event_timer_arm_tmo_tick_burst( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + const uint64_t timeout_ticks, + const uint16_t nb_event_timers) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->arm_tmo_tick_burst, -EINVAL); + + if (!adapter->data->started) + return -EAGAIN; + + for (int i = 0; i < nb_event_timers; i++) + event_timers[i]->timeout_ticks = timeout_ticks; + + ret = adapter->arm_tmo_tick_burst(adapter, event_timers, timeout_ticks, + nb_event_timers); + if (ret < 0) + return ret; + + return 0; +} + +int +rte_event_timer_cancel_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + uint16_t nb_event_timers) +{ + int ret; + + ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL); + FUNC_PTR_OR_ERR_RET(adapter->cancel_burst, -EINVAL); + + if (!adapter->data->started) + return -EAGAIN; + + ret = adapter->cancel_burst(adapter, event_timers, nb_event_timers); + if (ret < 0) + return ret; + + return 0; +} diff --git a/lib/librte_eventdev/rte_event_timer_adapter.h b/lib/librte_eventdev/rte_event_timer_adapter.h new file mode 100644 index 0000000..14661b5 --- /dev/null +++ b/lib/librte_eventdev/rte_event_timer_adapter.h @@ -0,0 +1,427 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __RTE_EVENT_TIMER_ADAPTER_H__ +#define __RTE_EVENT_TIMER_ADAPTER_H__ + +/** + * @file + * + * RTE Event Timer Adapter + * + * TODO: description + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "rte_eventdev.h" + +#define RTE_EVENT_TIMER_ADAPTER_NUM_MAX 64 + +/** + * Timer adapter clock source + */ +enum rte_event_timer_adapter_clk_src { + RTE_EVENT_TIMER_ADAPTER_CPU_CLK, + /**< Use CPU clock as the clock source. */ + RTE_EVENT_TIMER_ADAPTER_EXT_CLK0, + /**< Platform dependent external clock source 0. */ + RTE_EVENT_TIMER_ADAPTER_EXT_CLK1, + /**< Platform dependent external clock source 1. */ + RTE_EVENT_TIMER_ADAPTER_EXT_CLK2, + /**< Platform dependent external clock source 2. */ + RTE_EVENT_TIMER_ADAPTER_EXT_CLK3, + /**< Platform dependent external clock source 3. */ +}; + +#define RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES (1ULL << 0) +/**< The event timer adapter implementation may have constraints on the + * resolution (timer_tick_ns) and maximum timer expiry timeout(max_tmo_ns) + * based on the given timer adapter or system. If this flag is set, the + * implementation adjusts the resolution and maximum timeout to the best + * possible configuration. On successful timer adapter creation, the + * application can get the configured resolution and max timeout with + * ``rte_event_timer_adapter_get_info()``. + */ +#define RTE_EVENT_TIMER_ADAPTER_F_SP_PUT (1ULL << 1) +/**< ``rte_event_timer_arm_burst()`` API to be used in single producer mode. + * + * @see struct rte_event_timer_adapter_conf::flags + */ + +/* + * Timer adapter configuration structure + */ +struct rte_event_timer_adapter_conf { + uint8_t event_dev_id; + /**< Event device identifier */ + uint16_t timer_adapter_id; + /**< Event timer adapter identifier */ + uint32_t socket_id; + /**< Identifer of socket from which to allocate memory for adapter */ + enum rte_event_timer_adapter_clk_src clk_src; + /**< Clock source for timer adapter */ + uint64_t timer_tick_ns; + /**< Timer adapter resolution in ns */ + uint64_t max_tmo_ns; + /**< Maximum timer timeout(expiry) in ns */ + uint64_t nb_timers; + /**< Total number of timers per adapter */ + uint64_t flags; + /**< Timer adapter config flags (RTE_EVENT_TIMER_ADAPTER_F_*) */ +}; + +struct rte_event_timer_adapter; + +/* + * Callback function type for producer port creation. + */ +typedef int (*rte_event_timer_adapter_port_conf_cb_t)(uint16_t id, + uint8_t event_dev_id, + uint8_t *event_port_id, + void *conf_arg); + +/* + * Create an event timer adapter. + * + * This function must be invoked first before any other function in the API. + * + * @param conf + * The event timer adapter configuration structure. + * + * @return + * A pointer to the new allocated event timer adapter on success. + * NULL on error with rte_errno set appropriately. + * Possible rte_errno values include: + * - ERANGE: timer_tick_ns is not in supported range. + */ +struct rte_event_timer_adapter *rte_event_timer_adapter_create( + const struct rte_event_timer_adapter_conf *conf); + +/* + * Create a timer adapter with the supplied callback. + * + * This function can be used to have a more granular control over the timer + * adapter creation. If a built-in port is absent, then the function uses the + * callback provided to create and get the port id to be used as a producer + * port. + * + * @param conf + * The timer adapter configuration structure + * @param conf_cb + * The port config callback function. + * @param conf_arg + * Opaque pointer to the argument for the callback function + * @param id_ptr[out] + * Address of variable to store adapter identifier in + * + * @return + * A pointer to the new allocated event timer adapter on success. + * NULL on error with rte_errno set appropriately. + * Possible rte_errno values include: + * - ERANGE: timer_tick_ns is not in supported range. + * - ENOMEM: unable to allocate sufficient memory for adapter instances + * - EINVAL: invalid event device identifier specified in config + * - ENOSPC: maximum number of adapters already created + */ +struct rte_event_timer_adapter *rte_event_timer_adapter_create_ext( + const struct rte_event_timer_adapter_conf *conf, + rte_event_timer_adapter_port_conf_cb_t conf_cb, + void *conf_arg); + +/* + * Timer adapter info structure. + */ +struct rte_event_timer_adapter_info { + uint64_t min_resolution_ns; + /**< Minimum timer adapter resolution in ns */ + uint64_t max_tmo_ns; + /**< Maximum timer timeout(expire) in ns */ + struct rte_event_timer_adapter_conf conf; + /**< Configured timer adapter attributes */ + uint32_t caps; + /**< Event timer adapter capabilities */ + int16_t event_dev_port_id; + /**< Event device port ID, if applicable */ + int32_t service_id; + /**< Service ID, if applicable */ +}; + +/** + * Retrieve the contextual information of an event timer adapter. + * + * @param adapter + * A pointer to the event timer adapter structure. + * + * @param[out] adapter_info + * A pointer to a structure of type *rte_event_timer_adapter_info* to be + * filled with the contextual information of the adapter. + * + * @return + * - 0: Success, driver updates the contextual information of the + * timer adapter + * - <0: Error code returned by the driver info get function. + * - -EINVAL if adapter identifier invalid + * + * @see RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES, + * struct rte_event_timer_adapter_info + * + */ +int rte_event_timer_adapter_get_info( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer_adapter_info *adapter_info); + +/** + * Start a timer adapter. + * + * The adapter start step is the last one and consists of setting the timer + * adapter to start accepting the timers and schedules to event queues. + * + * On success, all basic functions exported by the API (timer arm, + * timer cancel and so on) can be invoked. + * + * @param adapter + * A pointer to the event timer adapter structure. + * + * @return + * - 0: Success, adapter started. + * - <0: Error code returned by the driver start function. + * - -EINVAL if adapter identifier invalid + */ +int rte_event_timer_adapter_start( + const struct rte_event_timer_adapter *adapter); + +/** + * Stop an event timer adapter. + * + * The adapter can be restarted with a call to + * ``rte_event_timer_adapter_start()``. + * + * @param adapter + * A pointer to the event timer adapter structure. + * + * @return + * - 0: Success, adapter stopped. + * - <0: Error code returned by the driver stop function. + * - -EINVAL if adapter identifier invalid + */ +int rte_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter); + +/* + * Lookup an event timer adapter using its identifier. + * + * If an event timer adapter was created in another process with the same + * identifier, this function will locate its state and set up access to it + * so that it can be used in this process. + * + * @param adapter_id + * The event timer adapter identifier. + * + * @return + * A pointer to the event timer adapter matching the identifier on success. + * NULL on error with rte_errno set appropriately. + * Possible rte_errno values include: + * - ENOENT - required entry not available to return. + */ +struct rte_event_timer_adapter *rte_event_timer_adapter_lookup( + uint16_t adapter_id); + +/* + * Free an event timer adapter. + * + * Destroy an event timer adapter, freeing all resources. + * + * Before invoking this function, the application must wait for all the + * armed timers to expire or cancel the outstanding armed timers. + * + * @param adapter + * A pointer to an event timer adapter structure. + * + * @return + * - 0: Successfully freed the event timer adapter resources. + * - <0: Failed to free the event timer adapter resources. + * - -EAGAIN: adapter is busy; timers outstanding + * - -EBUSY: stop hasn't been called for this adapter yet + * - -EINVAL: adapter id invalid, or adapter invalid + */ +int rte_event_timer_adapter_free(struct rte_event_timer_adapter *adapter); + +/** + * Event timer state. + */ +enum rte_event_timer_state { + RTE_EVENT_TIMER_NOT_ARMED = 0, + /**< Event timer is in not armed state.*/ + RTE_EVENT_TIMER_ARMED = 1, + /**< Event timer successfully armed.*/ + RTE_EVENT_TIMER_ERROR = -1, + /**< Generic event timer error.*/ + RTE_EVENT_TIMER_ERROR_TOOEARLY = -2, + /**< Event timer timeout tick is too little to add to the adapter. */ + RTE_EVENT_TIMER_ERROR_TOOLATE = -3, + /**< Event timer timeout tick is greater than the maximum timeout.*/ +}; + +/** + * The generic *rte_event_timer* structure to hold the event timer attributes + * for arm and cancel operations. + */ +RTE_STD_C11 +struct rte_event_timer { + struct rte_event ev; + /**< + * Expiry event attributes. On successful event timer timeout, + * the following attributes will be used to inject the expiry event to + * the eventdev: + * - event_queue_id: Targeted event queue id for expiry events. + * - event_priority: Event priority of the event expiry event in the + * event queue relative to other events. + * - sched_type: Scheduling type of the expiry event. + * - flow_id: Flow id of the expiry event. + * - op: RTE_EVENT_OP_NEW + * - event_type: RTE_EVENT_TYPE_TIMER + */ + enum rte_event_timer_state state; + /**< State of the event timer. */ + uint64_t timeout_ticks; + /**< Expiry timer ticks expressed in number of *timer_ticks_ns* from + * now. + * @see struct rte_event_timer_adapter_info::adapter_conf::timer_tick_ns + */ + uint64_t impl_opaque[2]; + /**< Implementation-specific opaque data. + * An event timer adapter implementation use this field to hold + * implementation specific values to share between the arm and cancel + * operations. The application should not modify this field. + */ + uint8_t user_meta[]; + /**< Memory to store user specific metadata. + * The event timer adapter implementation should not modify this area. + */ +} __rte_cache_aligned; + +/** + * Arm a burst of event timers with separate expiration timeout tick for each + * event timer. + * + * Before calling this function, the application allocates + * ``struct rte_event_timer`` objects from mempool or huge page backed + * application buffers of desired size. On successful allocation, + * application updates the `struct rte_event_timer`` attributes such as + * expiry event attributes, timeout ticks from now. + * This function submits the event timer arm requests to the event timer adapter + * and on expiry, the events will be injected to designated event queue. + * + * @param adapter + * A pointer to an event timer adapter structure. + * @param event_timers + * Pointer to an array of objects of type *rte_event_timer* structure. + * @param nb_event_timers + * Number of event timers in the supplied array. + * + * @return + * The number of successfully armed event timers. The return value can be less + * than the value of the *nb_timers* parameter. If the return value is less + * than *nb_events*, the remaining event timers at the end of *tim* + * are not consumed, and the caller has to take care of them, and rte_errno + * is set accordingly. Possible errno values include: + * - -EINVAL Invalid timer adapter identifier, expiry event queue ID is + * invalid, or an expiry event's sched type doesn't match the capabilities of + * the destination event queue. + * - -EAGAIN Specified timer adapter is not running + */ +int rte_event_timer_arm_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + uint16_t nb_event_timers); + +/** + * Arm a burst of event timers with same expiration timeout tick. + * + * Provides the same functionality as ``rte_event_timer_arm_burst()``, except + * that application can use this API when all the event timers have the + * same timeout expiration tick. This specialized function can provide the + * additional hint to the adapter implementation and optimize if possible. + * + * @param adapter + * A pointer to an event timer adapter structure. + * @param event_timers + * Points to an array of objects of type *rte_event_timer* structure. + * @param timeout_ticks + * The number of ticks in which the timers should expire. + * @param nb_event_timers + * Number of event timers in the supplied array. + * + * @return + * The number of successfully armed event timers. The return value can be less + * than the value of the *nb_timers* parameter. If the return value is less + * than *nb_events*, the remaining event timers at the end of *tim* + * are not consumed, and the caller has to take care of them, and rte_errno + * is set accordingly. Possible errno values include: + * - -EINVAL Invalid timer adapter identifier, expiry event queue ID is + * invalid, or an expiry event's sched type doesn't match the capabilities of + * the destination event queue. + * - -EAGAIN Specified event timer adapter is not running + */ +int rte_event_timer_arm_tmo_tick_burst( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + const uint64_t timeout_ticks, + const uint16_t nb_event_timers); + +/** + * Cancel a burst of event timer from being scheduled to the event device. + * + * @param adapter + * A pointer to an event timer adapter structure. + * @param event_timers + * Points to an array of objects of type *rte_event_timer* structure + * @param nb_event_timers + * Number of event timer instances in the supplied array. + * + * @return + * The number of successfully canceled event timers. The return value can be + * less than the value of the *nb_timers* parameter. If the return value is + * less than *nb_events*, the remaining event timers at the end of *tim* + * are not consumed, and the caller has to take care of them, and rte_errno + * is set accordingly. Possible errno values include: + * - -EINVAL Invalid timer adapter identifier + * - -EAGAIN Specified timer adapter is not running + */ +int rte_event_timer_cancel_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **event_timers, + uint16_t nb_event_timers); + +#endif /* __RTE_EVENT_TIMER_ADAPTER_H__ */ diff --git a/lib/librte_eventdev/rte_event_timer_adapter_driver.h b/lib/librte_eventdev/rte_event_timer_adapter_driver.h new file mode 100644 index 0000000..485fad1 --- /dev/null +++ b/lib/librte_eventdev/rte_event_timer_adapter_driver.h @@ -0,0 +1,159 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RTE_EVENT_TIMER_ADAPTER_DRIVER_H__ +#define __RTE_EVENT_TIMER_ADAPTER_DRIVER_H__ + +/** + * @file + * + * Description + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rte_event_timer_adapter.h" + +/* + * Definitions of functions exported by an event timer adapter implementation + * through *rte_event_timer_adapter_ops* structure supplied in the + * *rte_event_timer_adapter* structure associated with an event timer adapter. + */ + +typedef int (*rte_event_timer_adapter_init_t)( + struct rte_event_timer_adapter *adapter); +/**< @internal Event timer adapter implementation setup */ +typedef int (*rte_event_timer_adapter_uninit_t)( + struct rte_event_timer_adapter *adapter); +/**< @internal Event timer adapter implementation teardown */ +typedef int (*rte_event_timer_adapter_start_t)( + const struct rte_event_timer_adapter *adapter); +/**< @internal Start running event timer adapter */ +typedef int (*rte_event_timer_adapter_stop_t)( + const struct rte_event_timer_adapter *adapter); +/**< @internal Stop running event timer adapter */ +typedef void (*rte_event_timer_adapter_get_info_t)( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer_adapter_info *adapter_info); +/**< @internal Get contextual information for event timer adapter */ +typedef int (*rte_event_timer_arm_burst_t)( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **tims, + uint16_t nb_tims); +/**< @internal Enable event timers to enqueue timer events upon expiry */ +typedef int (*rte_event_timer_arm_tmo_tick_burst_t)( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **tims, + uint64_t timeout_tick, + uint16_t nb_tims); +/**< @internal Enable event timers with common expiration time */ +typedef int (*rte_event_timer_cancel_burst_t)( + const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **tims, + uint16_t nb_tims); +/**< @internal Prevent event timers from enqueuing timer events */ + +/** + * @internal Structure containing the functions exported by an event timer + * adapter implementation. + */ +struct rte_event_timer_adapter_ops { + rte_event_timer_adapter_init_t init; /**< Set up adapter */ + rte_event_timer_adapter_uninit_t uninit;/**< Tear down adapter */ + rte_event_timer_adapter_start_t start; /**< Start adapter */ + rte_event_timer_adapter_stop_t stop; /**< Stop adapter */ + rte_event_timer_adapter_get_info_t get_info; + /**< Get info from driver */ + rte_event_timer_arm_burst_t arm_burst; + /**< Arm one or more event timers */ + rte_event_timer_arm_tmo_tick_burst_t arm_tmo_tick_burst; + /**< Arm event timers with same expiration time */ + rte_event_timer_cancel_burst_t cancel_burst; + /**< Cancel one or more event timers */ +}; + +/** + * @internal Adapter data; structure to be placed in shared memory to be + * accessible by various processes in a multi-process configuration. + */ +struct rte_event_timer_adapter_data { + uint8_t id; + /**< Event timer adapter ID */ + uint8_t event_dev_id; + /**< Event device ID */ + uint32_t socket_id; + /**< Socket ID where memory is allocated */ + uint8_t event_port_id; + /**< Optional: event port ID used when the inbuilt port is absent */ + const struct rte_memzone *mz; + /**< Event timer adapter memzone pointer */ + struct rte_event_timer_adapter_conf conf; + /**< Configuration used to configure the adapter. */ + uint32_t caps; + /**< Adapter capabilities */ + void *adapter_priv; + /**< Timer adapter private data*/ + + RTE_STD_C11 + uint8_t started : 1; + /**< Flag to indicate adapter started. */ +} __rte_cache_aligned; + +/** + * @internal Data structure associated with each event timer adapter. + */ +struct rte_event_timer_adapter { + rte_event_timer_arm_burst_t arm_burst; + /**< Pointer to driver arm_burst function. */ + rte_event_timer_arm_tmo_tick_burst_t arm_tmo_tick_burst; + /**< Pointer to driver arm_tmo_tick_burst function. */ + rte_event_timer_cancel_burst_t cancel_burst; + /**< Pointer to driver cancel function. */ + + struct rte_event_timer_adapter_data *data; + /**< Pointer to shared adapter data */ + const struct rte_event_timer_adapter_ops *ops; + /**< Functions exported by adapter driver */ + + RTE_STD_C11 + uint8_t allocated : 1; + /**< Flag to indicate that this adapter has been allocated */ +} __rte_cache_aligned; + +#ifdef __cplusplus +} +#endif + +#endif /* __RTE_EVENT_TIMER_ADAPTER_DRIVER_H__ */ diff --git a/lib/librte_eventdev/rte_eventdev.h b/lib/librte_eventdev/rte_eventdev.h index f1949ff..67360c1 100644 --- a/lib/librte_eventdev/rte_eventdev.h +++ b/lib/librte_eventdev/rte_eventdev.h @@ -1025,6 +1025,9 @@ struct rte_event { * @see struct rte_event_eth_rx_adapter_queue_conf::rx_queue_flags */ +#define RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT (1ULL << 1) +/**< This flag is set when the timer mechanism is in HW. */ + /** * Retrieve the event device's ethdev Rx adapter capabilities for the * specified ethernet port diff --git a/lib/librte_eventdev/rte_eventdev_pmd.h b/lib/librte_eventdev/rte_eventdev_pmd.h index 7a206c5..719fde3 100644 --- a/lib/librte_eventdev/rte_eventdev_pmd.h +++ b/lib/librte_eventdev/rte_eventdev_pmd.h @@ -52,6 +52,7 @@ extern "C" { #include #include "rte_eventdev.h" +#include "rte_event_timer_adapter_driver.h" /* Logging Macros */ #define RTE_EDEV_LOG_ERR(...) \ @@ -466,6 +467,9 @@ typedef int (*eventdev_eth_rx_adapter_caps_get_t) struct rte_event_eth_rx_adapter_queue_conf *queue_conf; +typedef int (*eventdev_timer_adapter_caps_get_t)(const struct rte_eventdev *dev, + uint32_t *caps, const struct rte_event_timer_adapter_ops **ops); + /** * Add ethernet Rx queues to event device. This callback is invoked if * the caps returned from rte_eventdev_eth_rx_adapter_caps_get(, eth_port_id) @@ -650,6 +654,9 @@ struct rte_eventdev_ops { /**< Get ethernet Rx stats */ eventdev_eth_rx_adapter_stats_reset eth_rx_adapter_stats_reset; /**< Reset ethernet Rx stats */ + + eventdev_timer_adapter_caps_get_t timer_adapter_caps_get; + /**< Get timer adapter capabilities */ }; /** diff --git a/lib/librte_eventdev/rte_eventdev_version.map b/lib/librte_eventdev/rte_eventdev_version.map index 108ae61..f56ca0f 100644 --- a/lib/librte_eventdev/rte_eventdev_version.map +++ b/lib/librte_eventdev/rte_eventdev_version.map @@ -66,5 +66,18 @@ DPDK_17.11 { rte_event_eth_rx_adapter_stats_get; rte_event_eth_rx_adapter_stats_reset; rte_event_eth_rx_adapter_stop; - } DPDK_17.08; + +DPDK_18.02 { + global: + + rte_event_timer_adapter_create; + rte_event_timer_adapter_create_ext; + rte_event_timer_adapter_free; + rte_event_timer_adapter_get_info; + rte_event_timer_adapter_start; + rte_event_timer_adapter_stop; + rte_event_timer_arm_burst; + rte_event_timer_arm_tmo_tick_burst; + rte_event_timer_cancel_burst; +} DPDK_17.11; diff --git a/lib/librte_eventdev/sw_event_timer_adapter.c b/lib/librte_eventdev/sw_event_timer_adapter.c new file mode 100644 index 0000000..43fdad2 --- /dev/null +++ b/lib/librte_eventdev/sw_event_timer_adapter.c @@ -0,0 +1,123 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rte_event_timer_adapter.h" +#include "rte_event_timer_adapter_driver.h" + +static int +sw_event_timer_adapter_init(struct rte_event_timer_adapter *adapter) +{ + RTE_SET_USED(adapter); + + return 0; +} + +static int +sw_event_timer_adapter_uninit(struct rte_event_timer_adapter *adapter) +{ + RTE_SET_USED(adapter); + + return 0; +} + +static int +sw_event_timer_adapter_start(const struct rte_event_timer_adapter *adapter) +{ + RTE_SET_USED(adapter); + + return 0; +} + +static int +sw_event_timer_adapter_stop(const struct rte_event_timer_adapter *adapter) +{ + RTE_SET_USED(adapter); + + return 0; +} + +static void +sw_event_timer_adapter_get_info(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer_adapter_info *adapter_info) +{ + RTE_SET_USED(adapter); + RTE_SET_USED(adapter_info); +} + +static int +sw_event_timer_arm_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **evtims, + uint16_t nb_evtims) +{ + RTE_SET_USED(adapter); + RTE_SET_USED(evtims); + RTE_SET_USED(nb_evtims); + + return 0; +} + +static int +sw_event_timer_cancel_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **evtims, + uint16_t nb_evtims) +{ + RTE_SET_USED(adapter); + RTE_SET_USED(evtims); + RTE_SET_USED(nb_evtims); + + return 0; +} + +static int +sw_event_timer_arm_tmo_tick_burst(const struct rte_event_timer_adapter *adapter, + struct rte_event_timer **tims, + uint64_t timeout_tick, + uint16_t nb_tims) +{ + RTE_SET_USED(adapter); + RTE_SET_USED(tims); + RTE_SET_USED(timeout_tick); + RTE_SET_USED(nb_tims); + + return 0; +} + +const struct rte_event_timer_adapter_ops sw_event_adapter_timer_ops = { + .init = sw_event_timer_adapter_init, + .uninit = sw_event_timer_adapter_uninit, + .start = sw_event_timer_adapter_start, + .stop = sw_event_timer_adapter_stop, + .get_info = sw_event_timer_adapter_get_info, + .arm_burst = sw_event_timer_arm_burst, + .arm_tmo_tick_burst = sw_event_timer_arm_tmo_tick_burst, + .cancel_burst = sw_event_timer_cancel_burst, +}; diff --git a/test/test/Makefile b/test/test/Makefile index bb54c98..9448aef 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -210,6 +210,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y) SRCS-y += test_eventdev.c SRCS-y += test_event_ring.c SRCS-y += test_event_eth_rx_adapter.c +SRCS-y += test_event_timer_adapter.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV) += test_eventdev_sw.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF) += test_eventdev_octeontx.c endif diff --git a/test/test/test_event_timer_adapter.c b/test/test/test_event_timer_adapter.c new file mode 100644 index 0000000..d0ea066 --- /dev/null +++ b/test/test/test_event_timer_adapter.c @@ -0,0 +1,249 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "test.h" + +/* Example from RFC */ +#define NB_TEST_EVENT_TIMERS 40000 + +static int evdev; +//struct rte_event_timer_adapter *g_adapter; +struct rte_event_timer *g_evtimer; +struct rte_mempool *g_event_timer_pool; + +static inline void +devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf, + struct rte_event_dev_info *info) +{ + memset(dev_conf, 0, sizeof(struct rte_event_dev_config)); + dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns; + /* Leave a port for the adapter to allocate */ + dev_conf->nb_event_ports = info->max_event_ports - 1; + dev_conf->nb_event_queues = info->max_event_queues; + dev_conf->nb_event_queue_flows = info->max_event_queue_flows; + dev_conf->nb_event_port_dequeue_depth = + info->max_event_port_dequeue_depth; + dev_conf->nb_event_port_enqueue_depth = + info->max_event_port_enqueue_depth; + dev_conf->nb_event_port_enqueue_depth = + info->max_event_port_enqueue_depth; + dev_conf->nb_events_limit = + info->max_num_events; +} + +static int +configure_event_dev(void) +{ + struct rte_event_dev_config devconf; + int ret; + const char *eventdev_name = "event_sw0"; + struct rte_event_dev_info info; + int i; + + evdev = rte_event_dev_get_dev_id(eventdev_name); + if (evdev < 0) { + if (rte_vdev_init(eventdev_name, NULL) < 0) { + printf("Error creating eventdev\n"); + return TEST_FAILED; + } + evdev = rte_event_dev_get_dev_id(eventdev_name); + if (evdev < 0) { + printf("Error finding newly created eventdev\n"); + return TEST_FAILED; + } + } + + ret = rte_event_dev_info_get(evdev, &info); + TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info"); + + devconf_set_default_sane_values(&devconf, &info); + + ret = rte_event_dev_configure(evdev, &devconf); + TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev"); + + /* Map the event_sw0 service to a service core */ + ret = rte_service_start_with_defaults(); + TEST_ASSERT_SUCCESS(ret, "Failed to start sw_evdev service"); + + /* Set up event queues */ + uint32_t queue_count; + TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, + RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count), + "Queue count get failed"); + + for (i = 0; i < (int)queue_count; i++) { + ret = rte_event_queue_setup(evdev, i, NULL); + TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", i); + } + + /* Set up event ports */ + uint32_t port_count; + TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, + RTE_EVENT_DEV_ATTR_PORT_COUNT, + &port_count), "Port count get failed"); + + for (i = 0; i < (int)port_count; i++) { + ret = rte_event_port_setup(evdev, i, NULL); + TEST_ASSERT_SUCCESS(ret, "Failed to setup port=%d", i); + /* Link each queues to all ports */ + ret = rte_event_port_link(evdev, i, NULL, NULL, 0); + TEST_ASSERT(ret >= 0, "Failed to link all queues port=%d", i); + } + + /* Start the event device */ + ret = rte_event_dev_start(evdev); + TEST_ASSERT_SUCCESS(ret, "Failed to start device"); + + return TEST_SUCCESS; +} + +static int +testsuite_setup(void) +{ + int ret; + + /* Setup and start event device. */ + ret = configure_event_dev(); + if (ret) { + printf("Failed to configure event dev\n"); + return TEST_FAILED; + } + + /* Create a mempool of event timers. */ + g_event_timer_pool = rte_mempool_create("event_timer_mempool", + NB_TEST_EVENT_TIMERS, + sizeof(struct rte_event_timer), + 0, + 0, + NULL, + NULL, + NULL, + NULL, + rte_socket_id(), + 0); + if (g_event_timer_pool == NULL) { + /* Failed to create event timer mempool. */ + printf("Failed to configure event timer mempool: %s\n", + rte_strerror(rte_errno)); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static void +testsuite_teardown(void) +{ + /* TODO: tear down adapter and evdev */ + + rte_mempool_free(g_event_timer_pool); +} + +#define NSECPERSEC 1E9 // No of ns for 1 sec + +static int +adapter_create_free(void) +{ + int ret; + int adapter_id = 0; + struct rte_event_timer_adapter *adapter; + + struct rte_event_timer_adapter_conf conf = { + .event_dev_id = evdev, + .timer_adapter_id = adapter_id, + .clk_src = RTE_EVENT_TIMER_ADAPTER_CPU_CLK, + .timer_tick_ns = NSECPERSEC / 10, // 100 milliseconds + .max_tmo_ns = 180 * NSECPERSEC, // 2 minutes + .nb_timers = NB_TEST_EVENT_TIMERS, + .flags = 0, + }; + + adapter = rte_event_timer_adapter_create(&conf); + if (adapter == NULL) { + printf("Failed to create adapter\n"); + return TEST_FAILED; + } + + /* Move to separate tests later; just verify plugin connections for + * now + */ + + struct rte_event_timer_adapter_info adapter_info; + ret = rte_event_timer_adapter_get_info(adapter, &adapter_info); + if (ret < 0) + return TEST_FAILED; + + ret = rte_event_timer_adapter_start(adapter); + if (ret < 0) + return TEST_FAILED; + + ret = rte_event_timer_adapter_stop(adapter); + if (ret < 0) + return TEST_FAILED; + + ret = rte_event_timer_adapter_free(adapter); + if (ret) { + printf("Failed to free adapter\n"); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static struct unit_test_suite adapter_tests = { + .suite_name = "event timer adapter test suite", + .setup = testsuite_setup, + .teardown = testsuite_teardown, + .unit_test_cases = { + TEST_CASE(adapter_create_free), + TEST_CASES_END() /**< NULL terminate unit test array */ + } +}; + +static int +test_event_timer_adapter_common(void) +{ + return unit_test_suite_runner(&adapter_tests); +} + +REGISTER_TEST_COMMAND(event_timer_adapter_autotest, + test_event_timer_adapter_common);