summaryrefslogtreecommitdiffstats
path: root/lib/librte_eventdev
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librte_eventdev')
-rw-r--r--lib/librte_eventdev/Makefile4
-rw-r--r--lib/librte_eventdev/meson.build8
-rw-r--r--lib/librte_eventdev/rte_event_eth_rx_adapter.c6
-rw-r--r--lib/librte_eventdev/rte_event_eth_rx_adapter.h4
-rw-r--r--lib/librte_eventdev/rte_event_eth_tx_adapter.c1138
-rw-r--r--lib/librte_eventdev/rte_event_eth_tx_adapter.h462
-rw-r--r--lib/librte_eventdev/rte_eventdev.c70
-rw-r--r--lib/librte_eventdev/rte_eventdev.h74
-rw-r--r--lib/librte_eventdev/rte_eventdev_pmd.h225
-rw-r--r--lib/librte_eventdev/rte_eventdev_version.map13
10 files changed, 1973 insertions, 31 deletions
diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile
index 47f599a6..94961870 100644
--- a/lib/librte_eventdev/Makefile
+++ b/lib/librte_eventdev/Makefile
@@ -8,7 +8,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
LIB = librte_eventdev.a
# library version
-LIBABIVER := 5
+LIBABIVER := 6
# build flags
CFLAGS += -DALLOW_EXPERIMENTAL_API
@@ -28,6 +28,7 @@ SRCS-y += rte_event_ring.c
SRCS-y += rte_event_eth_rx_adapter.c
SRCS-y += rte_event_timer_adapter.c
SRCS-y += rte_event_crypto_adapter.c
+SRCS-y += rte_event_eth_tx_adapter.c
# export include files
SYMLINK-y-include += rte_eventdev.h
@@ -39,6 +40,7 @@ SYMLINK-y-include += rte_event_eth_rx_adapter.h
SYMLINK-y-include += rte_event_timer_adapter.h
SYMLINK-y-include += rte_event_timer_adapter_pmd.h
SYMLINK-y-include += rte_event_crypto_adapter.h
+SYMLINK-y-include += rte_event_eth_tx_adapter.h
# versioning export map
EXPORT_MAP := rte_eventdev_version.map
diff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build
index 3cbaf298..6becfe86 100644
--- a/lib/librte_eventdev/meson.build
+++ b/lib/librte_eventdev/meson.build
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation
-version = 5
+version = 6
allow_experimental_apis = true
if host_machine.system() == 'linux'
@@ -14,7 +14,8 @@ sources = files('rte_eventdev.c',
'rte_event_ring.c',
'rte_event_eth_rx_adapter.c',
'rte_event_timer_adapter.c',
- 'rte_event_crypto_adapter.c')
+ 'rte_event_crypto_adapter.c',
+ 'rte_event_eth_tx_adapter.c')
headers = files('rte_eventdev.h',
'rte_eventdev_pmd.h',
'rte_eventdev_pmd_pci.h',
@@ -23,5 +24,6 @@ headers = files('rte_eventdev.h',
'rte_event_eth_rx_adapter.h',
'rte_event_timer_adapter.h',
'rte_event_timer_adapter_pmd.h',
- 'rte_event_crypto_adapter.h')
+ 'rte_event_crypto_adapter.h',
+ 'rte_event_eth_tx_adapter.h')
deps += ['ring', 'ethdev', 'hash', 'mempool', 'mbuf', 'timer', 'cryptodev']
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index f5e5a0b5..71d008cd 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -1125,7 +1125,6 @@ rxa_poll(struct rte_event_eth_rx_adapter *rx_adapter)
wrr_pos = rx_adapter->wrr_pos;
max_nb_rx = rx_adapter->max_nb_rx;
buf = &rx_adapter->event_enqueue_buffer;
- stats = &rx_adapter->stats;
/* Iterate through a WRR sequence */
for (num_queue = 0; num_queue < rx_adapter->wrr_len; num_queue++) {
@@ -1998,8 +1997,7 @@ rte_event_eth_rx_adapter_create_ext(uint8_t id, uint8_t dev_id,
rx_adapter->id = id;
strcpy(rx_adapter->mem_name, mem_name);
rx_adapter->eth_devices = rte_zmalloc_socket(rx_adapter->mem_name,
- /* FIXME: incompatible with hotplug */
- rte_eth_dev_count_total() *
+ RTE_MAX_ETHPORTS *
sizeof(struct eth_device_info), 0,
socket_id);
rte_convert_rss_key((const uint32_t *)default_rss_key,
@@ -2012,7 +2010,7 @@ rte_event_eth_rx_adapter_create_ext(uint8_t id, uint8_t dev_id,
return -ENOMEM;
}
rte_spinlock_init(&rx_adapter->rx_lock);
- RTE_ETH_FOREACH_DEV(i)
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++)
rx_adapter->eth_devices[i].dev = &rte_eth_devices[i];
event_eth_rx_adapter[id] = rx_adapter;
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.h b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
index 332ee216..863b72a1 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.h
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
@@ -76,10 +76,6 @@
* rte_event_eth_rx_adapter_cb_register() function allows the
* application to register a callback that selects which packets to enqueue
* to the event device.
- *
- * Note:
- * 1) Devices created after an instance of rte_event_eth_rx_adapter_create
- * should be added to a new instance of the rx adapter.
*/
#ifdef __cplusplus
diff --git a/lib/librte_eventdev/rte_event_eth_tx_adapter.c b/lib/librte_eventdev/rte_event_eth_tx_adapter.c
new file mode 100644
index 00000000..3a21defb
--- /dev/null
+++ b/lib/librte_eventdev/rte_event_eth_tx_adapter.c
@@ -0,0 +1,1138 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation.
+ */
+#include <rte_spinlock.h>
+#include <rte_service_component.h>
+#include <rte_ethdev.h>
+
+#include "rte_eventdev_pmd.h"
+#include "rte_event_eth_tx_adapter.h"
+
+#define TXA_BATCH_SIZE 32
+#define TXA_SERVICE_NAME_LEN 32
+#define TXA_MEM_NAME_LEN 32
+#define TXA_FLUSH_THRESHOLD 1024
+#define TXA_RETRY_CNT 100
+#define TXA_MAX_NB_TX 128
+#define TXA_INVALID_DEV_ID INT32_C(-1)
+#define TXA_INVALID_SERVICE_ID INT64_C(-1)
+
+#define txa_evdev(id) (&rte_eventdevs[txa_dev_id_array[(id)]])
+
+#define txa_dev_caps_get(id) txa_evdev((id))->dev_ops->eth_tx_adapter_caps_get
+
+#define txa_dev_adapter_create(t) txa_evdev(t)->dev_ops->eth_tx_adapter_create
+
+#define txa_dev_adapter_create_ext(t) \
+ txa_evdev(t)->dev_ops->eth_tx_adapter_create
+
+#define txa_dev_adapter_free(t) txa_evdev(t)->dev_ops->eth_tx_adapter_free
+
+#define txa_dev_queue_add(id) txa_evdev(id)->dev_ops->eth_tx_adapter_queue_add
+
+#define txa_dev_queue_del(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_del
+
+#define txa_dev_start(t) txa_evdev(t)->dev_ops->eth_tx_adapter_start
+
+#define txa_dev_stop(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stop
+
+#define txa_dev_stats_reset(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_reset
+
+#define txa_dev_stats_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_get
+
+#define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
+do { \
+ if (!txa_valid_id(id)) { \
+ RTE_EDEV_LOG_ERR("Invalid eth Rx adapter id = %d", id); \
+ return retval; \
+ } \
+} while (0)
+
+#define TXA_CHECK_OR_ERR_RET(id) \
+do {\
+ int ret; \
+ RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET((id), -EINVAL); \
+ ret = txa_init(); \
+ if (ret != 0) \
+ return ret; \
+ if (!txa_adapter_exist((id))) \
+ return -EINVAL; \
+} while (0)
+
+/* Tx retry callback structure */
+struct txa_retry {
+ /* Ethernet port id */
+ uint16_t port_id;
+ /* Tx queue */
+ uint16_t tx_queue;
+ /* Adapter ID */
+ uint8_t id;
+};
+
+/* Per queue structure */
+struct txa_service_queue_info {
+ /* Queue has been added */
+ uint8_t added;
+ /* Retry callback argument */
+ struct txa_retry txa_retry;
+ /* Tx buffer */
+ struct rte_eth_dev_tx_buffer *tx_buf;
+};
+
+/* PMD private structure */
+struct txa_service_data {
+ /* Max mbufs processed in any service function invocation */
+ uint32_t max_nb_tx;
+ /* Number of Tx queues in adapter */
+ uint32_t nb_queues;
+ /* Synchronization with data path */
+ rte_spinlock_t tx_lock;
+ /* Event port ID */
+ uint8_t port_id;
+ /* Event device identifier */
+ uint8_t eventdev_id;
+ /* Highest port id supported + 1 */
+ uint16_t dev_count;
+ /* Loop count to flush Tx buffers */
+ int loop_cnt;
+ /* Per ethernet device structure */
+ struct txa_service_ethdev *txa_ethdev;
+ /* Statistics */
+ struct rte_event_eth_tx_adapter_stats stats;
+ /* Adapter Identifier */
+ uint8_t id;
+ /* Conf arg must be freed */
+ uint8_t conf_free;
+ /* Configuration callback */
+ rte_event_eth_tx_adapter_conf_cb conf_cb;
+ /* Configuration callback argument */
+ void *conf_arg;
+ /* socket id */
+ int socket_id;
+ /* Per adapter EAL service */
+ int64_t service_id;
+ /* Memory allocation name */
+ char mem_name[TXA_MEM_NAME_LEN];
+} __rte_cache_aligned;
+
+/* Per eth device structure */
+struct txa_service_ethdev {
+ /* Pointer to ethernet device */
+ struct rte_eth_dev *dev;
+ /* Number of queues added */
+ uint16_t nb_queues;
+ /* PMD specific queue data */
+ void *queues;
+};
+
+/* Array of adapter instances, initialized with event device id
+ * when adapter is created
+ */
+static int *txa_dev_id_array;
+
+/* Array of pointers to service implementation data */
+static struct txa_service_data **txa_service_data_array;
+
+static int32_t txa_service_func(void *args);
+static int txa_service_adapter_create_ext(uint8_t id,
+ struct rte_eventdev *dev,
+ rte_event_eth_tx_adapter_conf_cb conf_cb,
+ void *conf_arg);
+static int txa_service_queue_del(uint8_t id,
+ const struct rte_eth_dev *dev,
+ int32_t tx_queue_id);
+
+static int
+txa_adapter_exist(uint8_t id)
+{
+ return txa_dev_id_array[id] != TXA_INVALID_DEV_ID;
+}
+
+static inline int
+txa_valid_id(uint8_t id)
+{
+ return id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;
+}
+
+static void *
+txa_memzone_array_get(const char *name, unsigned int elt_size, int nb_elems)
+{
+ const struct rte_memzone *mz;
+ unsigned int sz;
+
+ sz = elt_size * nb_elems;
+ sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
+
+ mz = rte_memzone_lookup(name);
+ if (mz == NULL) {
+ mz = rte_memzone_reserve_aligned(name, sz, rte_socket_id(), 0,
+ RTE_CACHE_LINE_SIZE);
+ if (mz == NULL) {
+ RTE_EDEV_LOG_ERR("failed to reserve memzone"
+ " name = %s err = %"
+ PRId32, name, rte_errno);
+ return NULL;
+ }
+ }
+
+ return mz->addr;
+}
+
+static int
+txa_dev_id_array_init(void)
+{
+ if (txa_dev_id_array == NULL) {
+ int i;
+
+ txa_dev_id_array = txa_memzone_array_get("txa_adapter_array",
+ sizeof(int),
+ RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
+ if (txa_dev_id_array == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
+ txa_dev_id_array[i] = TXA_INVALID_DEV_ID;
+ }
+
+ return 0;
+}
+
+static int
+txa_init(void)
+{
+ return txa_dev_id_array_init();
+}
+
+static int
+txa_service_data_init(void)
+{
+ if (txa_service_data_array == NULL) {
+ txa_service_data_array =
+ txa_memzone_array_get("txa_service_data_array",
+ sizeof(int),
+ RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
+ if (txa_service_data_array == NULL)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline struct txa_service_data *
+txa_service_id_to_data(uint8_t id)
+{
+ return txa_service_data_array[id];
+}
+
+static inline struct txa_service_queue_info *
+txa_service_queue(struct txa_service_data *txa, uint16_t port_id,
+ uint16_t tx_queue_id)
+{
+ struct txa_service_queue_info *tqi;
+
+ if (unlikely(txa->txa_ethdev == NULL || txa->dev_count < port_id + 1))
+ return NULL;
+
+ tqi = txa->txa_ethdev[port_id].queues;
+
+ return likely(tqi != NULL) ? tqi + tx_queue_id : NULL;
+}
+
+static int
+txa_service_conf_cb(uint8_t __rte_unused id, uint8_t dev_id,
+ struct rte_event_eth_tx_adapter_conf *conf, void *arg)
+{
+ int ret;
+ struct rte_eventdev *dev;
+ struct rte_event_port_conf *pc;
+ struct rte_event_dev_config dev_conf;
+ int started;
+ uint8_t port_id;
+
+ pc = arg;
+ dev = &rte_eventdevs[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) {
+ RTE_EDEV_LOG_ERR("failed to configure event dev %u",
+ dev_id);
+ if (started) {
+ if (rte_event_dev_start(dev_id))
+ return -EIO;
+ }
+ return ret;
+ }
+
+ pc->disable_implicit_release = 0;
+ ret = rte_event_port_setup(dev_id, port_id, pc);
+ if (ret) {
+ RTE_EDEV_LOG_ERR("failed to setup event port %u\n",
+ port_id);
+ if (started) {
+ if (rte_event_dev_start(dev_id))
+ return -EIO;
+ }
+ return ret;
+ }
+
+ conf->event_port_id = port_id;
+ conf->max_nb_tx = TXA_MAX_NB_TX;
+ if (started)
+ ret = rte_event_dev_start(dev_id);
+ return ret;
+}
+
+static int
+txa_service_ethdev_alloc(struct txa_service_data *txa)
+{
+ struct txa_service_ethdev *txa_ethdev;
+ uint16_t i, dev_count;
+
+ dev_count = rte_eth_dev_count_avail();
+ if (txa->txa_ethdev && dev_count == txa->dev_count)
+ return 0;
+
+ txa_ethdev = rte_zmalloc_socket(txa->mem_name,
+ dev_count * sizeof(*txa_ethdev),
+ 0,
+ txa->socket_id);
+ if (txa_ethdev == NULL) {
+ RTE_EDEV_LOG_ERR("Failed to alloc txa::txa_ethdev ");
+ return -ENOMEM;
+ }
+
+ if (txa->dev_count)
+ memcpy(txa_ethdev, txa->txa_ethdev,
+ txa->dev_count * sizeof(*txa_ethdev));
+
+ RTE_ETH_FOREACH_DEV(i) {
+ if (i == dev_count)
+ break;
+ txa_ethdev[i].dev = &rte_eth_devices[i];
+ }
+
+ txa->txa_ethdev = txa_ethdev;
+ txa->dev_count = dev_count;
+ return 0;
+}
+
+static int
+txa_service_queue_array_alloc(struct txa_service_data *txa,
+ uint16_t port_id)
+{
+ struct txa_service_queue_info *tqi;
+ uint16_t nb_queue;
+ int ret;
+
+ ret = txa_service_ethdev_alloc(txa);
+ if (ret != 0)
+ return ret;
+
+ if (txa->txa_ethdev[port_id].queues)
+ return 0;
+
+ nb_queue = txa->txa_ethdev[port_id].dev->data->nb_tx_queues;
+ tqi = rte_zmalloc_socket(txa->mem_name,
+ nb_queue *
+ sizeof(struct txa_service_queue_info), 0,
+ txa->socket_id);
+ if (tqi == NULL)
+ return -ENOMEM;
+ txa->txa_ethdev[port_id].queues = tqi;
+ return 0;
+}
+
+static void
+txa_service_queue_array_free(struct txa_service_data *txa,
+ uint16_t port_id)
+{
+ struct txa_service_ethdev *txa_ethdev;
+ struct txa_service_queue_info *tqi;
+
+ txa_ethdev = &txa->txa_ethdev[port_id];
+ if (txa->txa_ethdev == NULL || txa_ethdev->nb_queues != 0)
+ return;
+
+ tqi = txa_ethdev->queues;
+ txa_ethdev->queues = NULL;
+ rte_free(tqi);
+
+ if (txa->nb_queues == 0) {
+ rte_free(txa->txa_ethdev);
+ txa->txa_ethdev = NULL;
+ }
+}
+
+static void
+txa_service_unregister(struct txa_service_data *txa)
+{
+ if (txa->service_id != TXA_INVALID_SERVICE_ID) {
+ rte_service_component_runstate_set(txa->service_id, 0);
+ while (rte_service_may_be_active(txa->service_id))
+ rte_pause();
+ rte_service_component_unregister(txa->service_id);
+ }
+ txa->service_id = TXA_INVALID_SERVICE_ID;
+}
+
+static int
+txa_service_register(struct txa_service_data *txa)
+{
+ int ret;
+ struct rte_service_spec service;
+ struct rte_event_eth_tx_adapter_conf conf;
+
+ if (txa->service_id != TXA_INVALID_SERVICE_ID)
+ return 0;
+
+ memset(&service, 0, sizeof(service));
+ snprintf(service.name, TXA_SERVICE_NAME_LEN, "txa_%d", txa->id);
+ service.socket_id = txa->socket_id;
+ service.callback = txa_service_func;
+ service.callback_userdata = txa;
+ service.capabilities = RTE_SERVICE_CAP_MT_SAFE;
+ ret = rte_service_component_register(&service,
+ (uint32_t *)&txa->service_id);
+ if (ret) {
+ RTE_EDEV_LOG_ERR("failed to register service %s err = %"
+ PRId32, service.name, ret);
+ return ret;
+ }
+
+ ret = txa->conf_cb(txa->id, txa->eventdev_id, &conf, txa->conf_arg);
+ if (ret) {
+ txa_service_unregister(txa);
+ return ret;
+ }
+
+ rte_service_component_runstate_set(txa->service_id, 1);
+ txa->port_id = conf.event_port_id;
+ txa->max_nb_tx = conf.max_nb_tx;
+ return 0;
+}
+
+static struct rte_eth_dev_tx_buffer *
+txa_service_tx_buf_alloc(struct txa_service_data *txa,
+ const struct rte_eth_dev *dev)
+{
+ struct rte_eth_dev_tx_buffer *tb;
+ uint16_t port_id;
+
+ port_id = dev->data->port_id;
+ tb = rte_zmalloc_socket(txa->mem_name,
+ RTE_ETH_TX_BUFFER_SIZE(TXA_BATCH_SIZE),
+ 0,
+ rte_eth_dev_socket_id(port_id));
+ if (tb == NULL)
+ RTE_EDEV_LOG_ERR("Failed to allocate memory for tx buffer");
+ return tb;
+}
+
+static int
+txa_service_is_queue_added(struct txa_service_data *txa,
+ const struct rte_eth_dev *dev,
+ uint16_t tx_queue_id)
+{
+ struct txa_service_queue_info *tqi;
+
+ tqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);
+ return tqi && tqi->added;
+}
+
+static int
+txa_service_ctrl(uint8_t id, int start)
+{
+ int ret;
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ if (txa->service_id == TXA_INVALID_SERVICE_ID)
+ return 0;
+
+ ret = rte_service_runstate_set(txa->service_id, start);
+ if (ret == 0 && !start) {
+ while (rte_service_may_be_active(txa->service_id))
+ rte_pause();
+ }
+ return ret;
+}
+
+static void
+txa_service_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,
+ void *userdata)
+{
+ struct txa_retry *tr;
+ struct txa_service_data *data;
+ struct rte_event_eth_tx_adapter_stats *stats;
+ uint16_t sent = 0;
+ unsigned int retry = 0;
+ uint16_t i, n;
+
+ tr = (struct txa_retry *)(uintptr_t)userdata;
+ data = txa_service_id_to_data(tr->id);
+ stats = &data->stats;
+
+ do {
+ n = rte_eth_tx_burst(tr->port_id, tr->tx_queue,
+ &pkts[sent], unsent - sent);
+
+ sent += n;
+ } while (sent != unsent && retry++ < TXA_RETRY_CNT);
+
+ for (i = sent; i < unsent; i++)
+ rte_pktmbuf_free(pkts[i]);
+
+ stats->tx_retry += retry;
+ stats->tx_packets += sent;
+ stats->tx_dropped += unsent - sent;
+}
+
+static void
+txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
+ uint32_t n)
+{
+ uint32_t i;
+ uint16_t nb_tx;
+ struct rte_event_eth_tx_adapter_stats *stats;
+
+ stats = &txa->stats;
+
+ nb_tx = 0;
+ for (i = 0; i < n; i++) {
+ struct rte_mbuf *m;
+ uint16_t port;
+ uint16_t queue;
+ struct txa_service_queue_info *tqi;
+
+ m = ev[i].mbuf;
+ port = m->port;
+ queue = rte_event_eth_tx_adapter_txq_get(m);
+
+ tqi = txa_service_queue(txa, port, queue);
+ if (unlikely(tqi == NULL || !tqi->added)) {
+ rte_pktmbuf_free(m);
+ continue;
+ }
+
+ nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf, m);
+ }
+
+ stats->tx_packets += nb_tx;
+}
+
+static int32_t
+txa_service_func(void *args)
+{
+ struct txa_service_data *txa = args;
+ uint8_t dev_id;
+ uint8_t port;
+ uint16_t n;
+ uint32_t nb_tx, max_nb_tx;
+ struct rte_event ev[TXA_BATCH_SIZE];
+
+ dev_id = txa->eventdev_id;
+ max_nb_tx = txa->max_nb_tx;
+ port = txa->port_id;
+
+ if (txa->nb_queues == 0)
+ return 0;
+
+ if (!rte_spinlock_trylock(&txa->tx_lock))
+ return 0;
+
+ for (nb_tx = 0; nb_tx < max_nb_tx; nb_tx += n) {
+
+ n = rte_event_dequeue_burst(dev_id, port, ev, RTE_DIM(ev), 0);
+ if (!n)
+ break;
+ txa_service_tx(txa, ev, n);
+ }
+
+ if ((txa->loop_cnt++ & (TXA_FLUSH_THRESHOLD - 1)) == 0) {
+
+ struct txa_service_ethdev *tdi;
+ struct txa_service_queue_info *tqi;
+ struct rte_eth_dev *dev;
+ uint16_t i;
+
+ tdi = txa->txa_ethdev;
+ nb_tx = 0;
+
+ RTE_ETH_FOREACH_DEV(i) {
+ uint16_t q;
+
+ if (i == txa->dev_count)
+ break;
+
+ dev = tdi[i].dev;
+ if (tdi[i].nb_queues == 0)
+ continue;
+ for (q = 0; q < dev->data->nb_tx_queues; q++) {
+
+ tqi = txa_service_queue(txa, i, q);
+ if (unlikely(tqi == NULL || !tqi->added))
+ continue;
+
+ nb_tx += rte_eth_tx_buffer_flush(i, q,
+ tqi->tx_buf);
+ }
+ }
+
+ txa->stats.tx_packets += nb_tx;
+ }
+ rte_spinlock_unlock(&txa->tx_lock);
+ return 0;
+}
+
+static int
+txa_service_adapter_create(uint8_t id, struct rte_eventdev *dev,
+ struct rte_event_port_conf *port_conf)
+{
+ struct txa_service_data *txa;
+ struct rte_event_port_conf *cb_conf;
+ int ret;
+
+ cb_conf = rte_malloc(NULL, sizeof(*cb_conf), 0);
+ if (cb_conf == NULL)
+ return -ENOMEM;
+
+ *cb_conf = *port_conf;
+ ret = txa_service_adapter_create_ext(id, dev, txa_service_conf_cb,
+ cb_conf);
+ if (ret) {
+ rte_free(cb_conf);
+ return ret;
+ }
+
+ txa = txa_service_id_to_data(id);
+ txa->conf_free = 1;
+ return ret;
+}
+
+static int
+txa_service_adapter_create_ext(uint8_t id, struct rte_eventdev *dev,
+ rte_event_eth_tx_adapter_conf_cb conf_cb,
+ void *conf_arg)
+{
+ struct txa_service_data *txa;
+ int socket_id;
+ char mem_name[TXA_SERVICE_NAME_LEN];
+ int ret;
+
+ if (conf_cb == NULL)
+ return -EINVAL;
+
+ socket_id = dev->data->socket_id;
+ snprintf(mem_name, TXA_MEM_NAME_LEN,
+ "rte_event_eth_txa_%d",
+ id);
+
+ ret = txa_service_data_init();
+ if (ret != 0)
+ return ret;
+
+ txa = rte_zmalloc_socket(mem_name,
+ sizeof(*txa),
+ RTE_CACHE_LINE_SIZE, socket_id);
+ if (txa == NULL) {
+ RTE_EDEV_LOG_ERR("failed to get mem for tx adapter");
+ return -ENOMEM;
+ }
+
+ txa->id = id;
+ txa->eventdev_id = dev->data->dev_id;
+ txa->socket_id = socket_id;
+ strncpy(txa->mem_name, mem_name, TXA_SERVICE_NAME_LEN);
+ txa->conf_cb = conf_cb;
+ txa->conf_arg = conf_arg;
+ txa->service_id = TXA_INVALID_SERVICE_ID;
+ rte_spinlock_init(&txa->tx_lock);
+ txa_service_data_array[id] = txa;
+
+ return 0;
+}
+
+static int
+txa_service_event_port_get(uint8_t id, uint8_t *port)
+{
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ if (txa->service_id == TXA_INVALID_SERVICE_ID)
+ return -ENODEV;
+
+ *port = txa->port_id;
+ return 0;
+}
+
+static int
+txa_service_adapter_free(uint8_t id)
+{
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ if (txa->nb_queues) {
+ RTE_EDEV_LOG_ERR("%" PRIu16 " Tx queues not deleted",
+ txa->nb_queues);
+ return -EBUSY;
+ }
+
+ if (txa->conf_free)
+ rte_free(txa->conf_arg);
+ rte_free(txa);
+ return 0;
+}
+
+static int
+txa_service_queue_add(uint8_t id,
+ __rte_unused struct rte_eventdev *dev,
+ const struct rte_eth_dev *eth_dev,
+ int32_t tx_queue_id)
+{
+ struct txa_service_data *txa;
+ struct txa_service_ethdev *tdi;
+ struct txa_service_queue_info *tqi;
+ struct rte_eth_dev_tx_buffer *tb;
+ struct txa_retry *txa_retry;
+ int ret;
+
+ txa = txa_service_id_to_data(id);
+
+ if (tx_queue_id == -1) {
+ int nb_queues;
+ uint16_t i, j;
+ uint16_t *qdone;
+
+ nb_queues = eth_dev->data->nb_tx_queues;
+ if (txa->dev_count > eth_dev->data->port_id) {
+ tdi = &txa->txa_ethdev[eth_dev->data->port_id];
+ nb_queues -= tdi->nb_queues;
+ }
+
+ qdone = rte_zmalloc(txa->mem_name,
+ nb_queues * sizeof(*qdone), 0);
+ j = 0;
+ for (i = 0; i < nb_queues; i++) {
+ if (txa_service_is_queue_added(txa, eth_dev, i))
+ continue;
+ ret = txa_service_queue_add(id, dev, eth_dev, i);
+ if (ret == 0)
+ qdone[j++] = i;
+ else
+ break;
+ }
+
+ if (i != nb_queues) {
+ for (i = 0; i < j; i++)
+ txa_service_queue_del(id, eth_dev, qdone[i]);
+ }
+ rte_free(qdone);
+ return ret;
+ }
+
+ ret = txa_service_register(txa);
+ if (ret)
+ return ret;
+
+ rte_spinlock_lock(&txa->tx_lock);
+
+ if (txa_service_is_queue_added(txa, eth_dev, tx_queue_id)) {
+ rte_spinlock_unlock(&txa->tx_lock);
+ return 0;
+ }
+
+ ret = txa_service_queue_array_alloc(txa, eth_dev->data->port_id);
+ if (ret)
+ goto err_unlock;
+
+ tb = txa_service_tx_buf_alloc(txa, eth_dev);
+ if (tb == NULL)
+ goto err_unlock;
+
+ tdi = &txa->txa_ethdev[eth_dev->data->port_id];
+ tqi = txa_service_queue(txa, eth_dev->data->port_id, tx_queue_id);
+
+ txa_retry = &tqi->txa_retry;
+ txa_retry->id = txa->id;
+ txa_retry->port_id = eth_dev->data->port_id;
+ txa_retry->tx_queue = tx_queue_id;
+
+ rte_eth_tx_buffer_init(tb, TXA_BATCH_SIZE);
+ rte_eth_tx_buffer_set_err_callback(tb,
+ txa_service_buffer_retry, txa_retry);
+
+ tqi->tx_buf = tb;
+ tqi->added = 1;
+ tdi->nb_queues++;
+ txa->nb_queues++;
+
+err_unlock:
+ if (txa->nb_queues == 0) {
+ txa_service_queue_array_free(txa,
+ eth_dev->data->port_id);
+ txa_service_unregister(txa);
+ }
+
+ rte_spinlock_unlock(&txa->tx_lock);
+ return 0;
+}
+
+static int
+txa_service_queue_del(uint8_t id,
+ const struct rte_eth_dev *dev,
+ int32_t tx_queue_id)
+{
+ struct txa_service_data *txa;
+ struct txa_service_queue_info *tqi;
+ struct rte_eth_dev_tx_buffer *tb;
+ uint16_t port_id;
+
+ if (tx_queue_id == -1) {
+ uint16_t i;
+ int ret = -1;
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ ret = txa_service_queue_del(id, dev, i);
+ if (ret != 0)
+ break;
+ }
+ return ret;
+ }
+
+ txa = txa_service_id_to_data(id);
+ port_id = dev->data->port_id;
+
+ tqi = txa_service_queue(txa, port_id, tx_queue_id);
+ if (tqi == NULL || !tqi->added)
+ return 0;
+
+ tb = tqi->tx_buf;
+ tqi->added = 0;
+ tqi->tx_buf = NULL;
+ rte_free(tb);
+ txa->nb_queues--;
+ txa->txa_ethdev[port_id].nb_queues--;
+
+ txa_service_queue_array_free(txa, port_id);
+ return 0;
+}
+
+static int
+txa_service_id_get(uint8_t id, uint32_t *service_id)
+{
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ if (txa->service_id == TXA_INVALID_SERVICE_ID)
+ return -ESRCH;
+
+ if (service_id == NULL)
+ return -EINVAL;
+
+ *service_id = txa->service_id;
+ return 0;
+}
+
+static int
+txa_service_start(uint8_t id)
+{
+ return txa_service_ctrl(id, 1);
+}
+
+static int
+txa_service_stats_get(uint8_t id,
+ struct rte_event_eth_tx_adapter_stats *stats)
+{
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ *stats = txa->stats;
+ return 0;
+}
+
+static int
+txa_service_stats_reset(uint8_t id)
+{
+ struct txa_service_data *txa;
+
+ txa = txa_service_id_to_data(id);
+ memset(&txa->stats, 0, sizeof(txa->stats));
+ return 0;
+}
+
+static int
+txa_service_stop(uint8_t id)
+{
+ return txa_service_ctrl(id, 0);
+}
+
+
+int __rte_experimental
+rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,
+ struct rte_event_port_conf *port_conf)
+{
+ struct rte_eventdev *dev;
+ int ret;
+
+ if (port_conf == NULL)
+ return -EINVAL;
+
+ RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ dev = &rte_eventdevs[dev_id];
+
+ ret = txa_init();
+ if (ret != 0)
+ return ret;
+
+ if (txa_adapter_exist(id))
+ return -EEXIST;
+
+ txa_dev_id_array[id] = dev_id;
+ if (txa_dev_adapter_create(id))
+ ret = txa_dev_adapter_create(id)(id, dev);
+
+ if (ret != 0) {
+ txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
+ return ret;
+ }
+
+ ret = txa_service_adapter_create(id, dev, port_conf);
+ if (ret != 0) {
+ if (txa_dev_adapter_free(id))
+ txa_dev_adapter_free(id)(id, dev);
+ txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
+ return ret;
+ }
+
+ txa_dev_id_array[id] = dev_id;
+ return 0;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,
+ rte_event_eth_tx_adapter_conf_cb conf_cb,
+ void *conf_arg)
+{
+ struct rte_eventdev *dev;
+ int ret;
+
+ RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ ret = txa_init();
+ if (ret != 0)
+ return ret;
+
+ if (txa_adapter_exist(id))
+ return -EINVAL;
+
+ dev = &rte_eventdevs[dev_id];
+
+ txa_dev_id_array[id] = dev_id;
+ if (txa_dev_adapter_create_ext(id))
+ ret = txa_dev_adapter_create_ext(id)(id, dev);
+
+ if (ret != 0) {
+ txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
+ return ret;
+ }
+
+ ret = txa_service_adapter_create_ext(id, dev, conf_cb, conf_arg);
+ if (ret != 0) {
+ if (txa_dev_adapter_free(id))
+ txa_dev_adapter_free(id)(id, dev);
+ txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
+ return ret;
+ }
+
+ txa_dev_id_array[id] = dev_id;
+ return 0;
+}
+
+
+int __rte_experimental
+rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id)
+{
+ TXA_CHECK_OR_ERR_RET(id);
+
+ return txa_service_event_port_get(id, event_port_id);
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_free(uint8_t id)
+{
+ int ret;
+
+ TXA_CHECK_OR_ERR_RET(id);
+
+ ret = txa_dev_adapter_free(id) ?
+ txa_dev_adapter_free(id)(id, txa_evdev(id)) :
+ 0;
+
+ if (ret == 0)
+ ret = txa_service_adapter_free(id);
+ txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
+
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_queue_add(uint8_t id,
+ uint16_t eth_dev_id,
+ int32_t queue)
+{
+ struct rte_eth_dev *eth_dev;
+ int ret;
+ uint32_t caps;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
+ TXA_CHECK_OR_ERR_RET(id);
+
+ eth_dev = &rte_eth_devices[eth_dev_id];
+ if (queue != -1 && (uint16_t)queue >= eth_dev->data->nb_tx_queues) {
+ RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16,
+ (uint16_t)queue);
+ return -EINVAL;
+ }
+
+ caps = 0;
+ if (txa_dev_caps_get(id))
+ txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
+
+ if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
+ ret = txa_dev_queue_add(id) ?
+ txa_dev_queue_add(id)(id,
+ txa_evdev(id),
+ eth_dev,
+ queue) : 0;
+ else
+ ret = txa_service_queue_add(id, txa_evdev(id), eth_dev, queue);
+
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_queue_del(uint8_t id,
+ uint16_t eth_dev_id,
+ int32_t queue)
+{
+ struct rte_eth_dev *eth_dev;
+ int ret;
+ uint32_t caps;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
+ TXA_CHECK_OR_ERR_RET(id);
+
+ eth_dev = &rte_eth_devices[eth_dev_id];
+ if (queue != -1 && (uint16_t)queue >= eth_dev->data->nb_tx_queues) {
+ RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16,
+ (uint16_t)queue);
+ return -EINVAL;
+ }
+
+ caps = 0;
+
+ if (txa_dev_caps_get(id))
+ txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
+
+ if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
+ ret = txa_dev_queue_del(id) ?
+ txa_dev_queue_del(id)(id, txa_evdev(id),
+ eth_dev,
+ queue) : 0;
+ else
+ ret = txa_service_queue_del(id, eth_dev, queue);
+
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id)
+{
+ TXA_CHECK_OR_ERR_RET(id);
+
+ return txa_service_id_get(id, service_id);
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_start(uint8_t id)
+{
+ int ret;
+
+ TXA_CHECK_OR_ERR_RET(id);
+
+ ret = txa_dev_start(id) ? txa_dev_start(id)(id, txa_evdev(id)) : 0;
+ if (ret == 0)
+ ret = txa_service_start(id);
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_stats_get(uint8_t id,
+ struct rte_event_eth_tx_adapter_stats *stats)
+{
+ int ret;
+
+ TXA_CHECK_OR_ERR_RET(id);
+
+ if (stats == NULL)
+ return -EINVAL;
+
+ *stats = (struct rte_event_eth_tx_adapter_stats){0};
+
+ ret = txa_dev_stats_get(id) ?
+ txa_dev_stats_get(id)(id, txa_evdev(id), stats) : 0;
+
+ if (ret == 0 && txa_service_id_get(id, NULL) != ESRCH) {
+ if (txa_dev_stats_get(id)) {
+ struct rte_event_eth_tx_adapter_stats service_stats;
+
+ ret = txa_service_stats_get(id, &service_stats);
+ if (ret == 0) {
+ stats->tx_retry += service_stats.tx_retry;
+ stats->tx_packets += service_stats.tx_packets;
+ stats->tx_dropped += service_stats.tx_dropped;
+ }
+ } else
+ ret = txa_service_stats_get(id, stats);
+ }
+
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_stats_reset(uint8_t id)
+{
+ int ret;
+
+ TXA_CHECK_OR_ERR_RET(id);
+
+ ret = txa_dev_stats_reset(id) ?
+ txa_dev_stats_reset(id)(id, txa_evdev(id)) : 0;
+ if (ret == 0)
+ ret = txa_service_stats_reset(id);
+ return ret;
+}
+
+int __rte_experimental
+rte_event_eth_tx_adapter_stop(uint8_t id)
+{
+ int ret;
+
+ TXA_CHECK_OR_ERR_RET(id);
+
+ ret = txa_dev_stop(id) ? txa_dev_stop(id)(id, txa_evdev(id)) : 0;
+ if (ret == 0)
+ ret = txa_service_stop(id);
+ return ret;
+}
diff --git a/lib/librte_eventdev/rte_event_eth_tx_adapter.h b/lib/librte_eventdev/rte_event_eth_tx_adapter.h
new file mode 100644
index 00000000..81456d4a
--- /dev/null
+++ b/lib/librte_eventdev/rte_event_eth_tx_adapter.h
@@ -0,0 +1,462 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation.
+ */
+
+#ifndef _RTE_EVENT_ETH_TX_ADAPTER_
+#define _RTE_EVENT_ETH_TX_ADAPTER_
+
+/**
+ * @file
+ *
+ * RTE Event Ethernet Tx Adapter
+ *
+ * The event ethernet Tx adapter provides configuration and data path APIs
+ * for the ethernet transmit stage of an event driven packet processing
+ * application. These APIs abstract the implementation of the transmit stage
+ * and allow the application to use eventdev PMD support or a common
+ * implementation.
+ *
+ * In the common implementation, the application enqueues mbufs to the adapter
+ * which runs as a rte_service function. The service function dequeues events
+ * from its event port and transmits the mbufs referenced by these events.
+ *
+ * The ethernet Tx event adapter APIs are:
+ *
+ * - rte_event_eth_tx_adapter_create()
+ * - rte_event_eth_tx_adapter_create_ext()
+ * - rte_event_eth_tx_adapter_free()
+ * - rte_event_eth_tx_adapter_start()
+ * - rte_event_eth_tx_adapter_stop()
+ * - rte_event_eth_tx_adapter_queue_add()
+ * - rte_event_eth_tx_adapter_queue_del()
+ * - rte_event_eth_tx_adapter_stats_get()
+ * - rte_event_eth_tx_adapter_stats_reset()
+ * - rte_event_eth_tx_adapter_enqueue()
+ * - rte_event_eth_tx_adapter_event_port_get()
+ * - rte_event_eth_tx_adapter_service_id_get()
+ *
+ * The application creates the adapter using
+ * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
+ *
+ * The adapter will use the common implementation when the eventdev PMD
+ * does not have the #RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT capability.
+ * The common implementation uses an event port that is created using the port
+ * configuration parameter passed to rte_event_eth_tx_adapter_create(). The
+ * application can get the port identifier using
+ * rte_event_eth_tx_adapter_event_port_get() and must link an event queue to
+ * this port.
+ *
+ * If the eventdev PMD has the #RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT
+ * flags set, Tx adapter events should be enqueued using the
+ * rte_event_eth_tx_adapter_enqueue() function, else the application should
+ * use rte_event_enqueue_burst().
+ *
+ * Transmit queues can be added and deleted from the adapter using
+ * rte_event_eth_tx_adapter_queue_add()/del() APIs respectively.
+ *
+ * The application can start and stop the adapter using the
+ * rte_event_eth_tx_adapter_start/stop() calls.
+ *
+ * The common adapter implementation uses an EAL service function as described
+ * before and its execution is controlled using the rte_service APIs. The
+ * rte_event_eth_tx_adapter_service_id_get()
+ * function can be used to retrieve the adapter's service function ID.
+ *
+ * The ethernet port and transmit queue index to transmit the mbuf on are
+ * specified using the mbuf port and the higher 16 bits of
+ * struct rte_mbuf::hash::sched:hi. The application should use the
+ * rte_event_eth_tx_adapter_txq_set() and rte_event_eth_tx_adapter_txq_get()
+ * functions to access the transmit queue index since it is expected that the
+ * transmit queue will be eventually defined within struct rte_mbuf and using
+ * these macros will help with minimizing application impact due to
+ * a change in how the transmit queue index is specified.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "rte_eventdev.h"
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Adapter configuration structure
+ *
+ * @see rte_event_eth_tx_adapter_create_ext
+ * @see rte_event_eth_tx_adapter_conf_cb
+ */
+struct rte_event_eth_tx_adapter_conf {
+ uint8_t event_port_id;
+ /**< Event port identifier, the adapter service function dequeues mbuf
+ * events from this port.
+ * @see RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT
+ */
+ uint32_t max_nb_tx;
+ /**< The adapter can return early if it has processed at least
+ * max_nb_tx mbufs. This isn't treated as a requirement; batching may
+ * cause the adapter to process more than max_nb_tx mbufs.
+ */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Function type used for adapter configuration callback. The callback is
+ * used to fill in members of the struct rte_event_eth_tx_adapter_conf, this
+ * callback is invoked when creating a RTE service function based
+ * adapter implementation.
+ *
+ * @param id
+ * Adapter identifier.
+ * @param dev_id
+ * Event device identifier.
+ * @param [out] conf
+ * Structure that needs to be populated by this callback.
+ * @param arg
+ * Argument to the callback. This is the same as the conf_arg passed to the
+ * rte_event_eth_tx_adapter_create_ext().
+ *
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+typedef int (*rte_event_eth_tx_adapter_conf_cb) (uint8_t id, uint8_t dev_id,
+ struct rte_event_eth_tx_adapter_conf *conf,
+ void *arg);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * A structure used to retrieve statistics for an ethernet Tx adapter instance.
+ */
+struct rte_event_eth_tx_adapter_stats {
+ uint64_t tx_retry;
+ /**< Number of transmit retries */
+ uint64_t tx_packets;
+ /**< Number of packets transmitted */
+ uint64_t tx_dropped;
+ /**< Number of packets dropped */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create a new ethernet Tx adapter with the specified identifier.
+ *
+ * @param id
+ * The identifier of the ethernet Tx adapter.
+ * @param dev_id
+ * The event device identifier.
+ * @param port_config
+ * Event port configuration, the adapter uses this configuration to
+ * create an event port if needed.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,
+ struct rte_event_port_conf *port_config);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create a new ethernet Tx adapter with the specified identifier.
+ *
+ * @param id
+ * The identifier of the ethernet Tx adapter.
+ * @param dev_id
+ * The event device identifier.
+ * @param conf_cb
+ * Callback function that initializes members of the
+ * struct rte_event_eth_tx_adapter_conf struct passed into
+ * it.
+ * @param conf_arg
+ * Argument that is passed to the conf_cb function.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,
+ rte_event_eth_tx_adapter_conf_cb conf_cb,
+ void *conf_arg);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Free an ethernet Tx adapter
+ *
+ * @param id
+ * Adapter identifier.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure, If the adapter still has Tx queues
+ * added to it, the function returns -EBUSY.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_free(uint8_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Start ethernet Tx adapter
+ *
+ * @param id
+ * Adapter identifier.
+ * @return
+ * - 0: Success, Adapter started correctly.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_start(uint8_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Stop ethernet Tx adapter
+ *
+ * @param id
+ * Adapter identifier.
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_stop(uint8_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Add a Tx queue to the adapter.
+ * A queue value of -1 is used to indicate all
+ * queues within the device.
+ *
+ * @param id
+ * Adapter identifier.
+ * @param eth_dev_id
+ * Ethernet Port Identifier.
+ * @param queue
+ * Tx queue index.
+ * @return
+ * - 0: Success, Queues added successfully.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_queue_add(uint8_t id,
+ uint16_t eth_dev_id,
+ int32_t queue);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Delete a Tx queue from the adapter.
+ * A queue value of -1 is used to indicate all
+ * queues within the device, that have been added to this
+ * adapter.
+ *
+ * @param id
+ * Adapter identifier.
+ * @param eth_dev_id
+ * Ethernet Port Identifier.
+ * @param queue
+ * Tx queue index.
+ * @return
+ * - 0: Success, Queues deleted successfully.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_queue_del(uint8_t id,
+ uint16_t eth_dev_id,
+ int32_t queue);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Set Tx queue in the mbuf. This queue is used by the adapter
+ * to transmit the mbuf.
+ *
+ * @param pkt
+ * Pointer to the mbuf.
+ * @param queue
+ * Tx queue index.
+ */
+static __rte_always_inline void __rte_experimental
+rte_event_eth_tx_adapter_txq_set(struct rte_mbuf *pkt, uint16_t queue)
+{
+ uint16_t *p = (uint16_t *)&pkt->hash.sched.hi;
+ p[1] = queue;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Retrieve Tx queue from the mbuf.
+ *
+ * @param pkt
+ * Pointer to the mbuf.
+ * @return
+ * Tx queue identifier.
+ *
+ * @see rte_event_eth_tx_adapter_txq_set()
+ */
+static __rte_always_inline uint16_t __rte_experimental
+rte_event_eth_tx_adapter_txq_get(struct rte_mbuf *pkt)
+{
+ uint16_t *p = (uint16_t *)&pkt->hash.sched.hi;
+ return p[1];
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Retrieve the adapter event port. The adapter creates an event port if
+ * the #RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT is not set in the
+ * ethernet Tx capabilities of the event device.
+ *
+ * @param id
+ * Adapter Identifier.
+ * @param[out] event_port_id
+ * Event port pointer.
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id);
+
+/**
+ * Enqueue a burst of events objects or an event object supplied in *rte_event*
+ * structure on an event device designated by its *dev_id* through the event
+ * port specified by *port_id*. This function is supported if the eventdev PMD
+ * has the #RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT capability flag set.
+ *
+ * The *nb_events* parameter is the number of event objects to enqueue which are
+ * supplied in the *ev* array of *rte_event* structure.
+ *
+ * The rte_event_eth_tx_adapter_enqueue() function returns the number of
+ * events objects it actually enqueued. A return value equal to *nb_events*
+ * means that all event objects have been enqueued.
+ *
+ * @param dev_id
+ * The identifier of the device.
+ * @param port_id
+ * The identifier of the event port.
+ * @param ev
+ * Points to an array of *nb_events* objects of type *rte_event* structure
+ * which contain the event object enqueue operations to be processed.
+ * @param nb_events
+ * The number of event objects to enqueue, typically number of
+ * rte_event_port_enqueue_depth() available for this port.
+ *
+ * @return
+ * The number of event objects actually enqueued on the event device. The
+ * return value can be less than the value of the *nb_events* parameter when
+ * the event devices queue is full or if invalid parameters are specified in a
+ * *rte_event*. If the return value is less than *nb_events*, the remaining
+ * events at the end of ev[] are not consumed and the caller has to take care
+ * of them, and rte_errno is set accordingly. Possible errno values include:
+ * - -EINVAL The port ID is invalid, device ID is invalid, an event's queue
+ * ID is invalid, or an event's sched type doesn't match the
+ * capabilities of the destination queue.
+ * - -ENOSPC The event port was backpressured and unable to enqueue
+ * one or more events. This error code is only applicable to
+ * closed systems.
+ */
+static inline uint16_t __rte_experimental
+rte_event_eth_tx_adapter_enqueue(uint8_t dev_id,
+ uint8_t port_id,
+ struct rte_event ev[],
+ uint16_t nb_events)
+{
+ const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
+ if (dev_id >= RTE_EVENT_MAX_DEVS ||
+ !rte_eventdevs[dev_id].attached) {
+ rte_errno = -EINVAL;
+ return 0;
+ }
+
+ if (port_id >= dev->data->nb_ports) {
+ rte_errno = -EINVAL;
+ return 0;
+ }
+#endif
+ return dev->txa_enqueue(dev->data->ports[port_id], ev, nb_events);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Retrieve statistics for an adapter
+ *
+ * @param id
+ * Adapter identifier.
+ * @param [out] stats
+ * A pointer to structure used to retrieve statistics for an adapter.
+ * @return
+ * - 0: Success, statistics retrieved successfully.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_stats_get(uint8_t id,
+ struct rte_event_eth_tx_adapter_stats *stats);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Reset statistics for an adapter.
+ *
+ * @param id
+ * Adapter identifier.
+ * @return
+ * - 0: Success, statistics reset successfully.
+ * - <0: Error code on failure.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_stats_reset(uint8_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Retrieve the service ID of an adapter. If the adapter doesn't use
+ * a rte_service function, this function returns -ESRCH.
+ *
+ * @param id
+ * Adapter identifier.
+ * @param [out] service_id
+ * A pointer to a uint32_t, to be filled in with the service id.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure, if the adapter doesn't use a rte_service
+ * function, this function returns -ESRCH.
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _RTE_EVENT_ETH_TX_ADAPTER_ */
diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c
index 801810ed..ebaf3087 100644
--- a/lib/librte_eventdev/rte_eventdev.c
+++ b/lib/librte_eventdev/rte_eventdev.c
@@ -35,22 +35,20 @@
#include "rte_eventdev.h"
#include "rte_eventdev_pmd.h"
-struct rte_eventdev rte_event_devices[RTE_EVENT_MAX_DEVS];
+static struct rte_eventdev rte_event_devices[RTE_EVENT_MAX_DEVS];
-struct rte_eventdev *rte_eventdevs = &rte_event_devices[0];
+struct rte_eventdev *rte_eventdevs = rte_event_devices;
static struct rte_eventdev_global eventdev_globals = {
.nb_devs = 0
};
-struct rte_eventdev_global *rte_eventdev_globals = &eventdev_globals;
-
/* Event dev north bound API implementation */
uint8_t
rte_event_dev_count(void)
{
- return rte_eventdev_globals->nb_devs;
+ return eventdev_globals.nb_devs;
}
int
@@ -62,7 +60,7 @@ rte_event_dev_get_dev_id(const char *name)
if (!name)
return -EINVAL;
- for (i = 0; i < rte_eventdev_globals->nb_devs; i++) {
+ for (i = 0; i < eventdev_globals.nb_devs; i++) {
cmp = (strncmp(rte_event_devices[i].data->name, name,
RTE_EVENTDEV_NAME_MAX_LEN) == 0) ||
(rte_event_devices[i].dev ? (strncmp(
@@ -109,7 +107,7 @@ rte_event_dev_info_get(uint8_t dev_id, struct rte_event_dev_info *dev_info)
}
int
-rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint8_t eth_port_id,
+rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
uint32_t *caps)
{
struct rte_eventdev *dev;
@@ -175,6 +173,31 @@ rte_event_crypto_adapter_caps_get(uint8_t dev_id, uint8_t cdev_id,
(dev, cdev, caps) : -ENOTSUP;
}
+int __rte_experimental
+rte_event_eth_tx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
+ uint32_t *caps)
+{
+ struct rte_eventdev *dev;
+ struct rte_eth_dev *eth_dev;
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_port_id, -EINVAL);
+
+ dev = &rte_eventdevs[dev_id];
+ eth_dev = &rte_eth_devices[eth_port_id];
+
+ if (caps == NULL)
+ return -EINVAL;
+
+ *caps = 0;
+
+ return dev->dev_ops->eth_tx_adapter_caps_get ?
+ (*dev->dev_ops->eth_tx_adapter_caps_get)(dev,
+ eth_dev,
+ caps)
+ : 0;
+}
+
static inline int
rte_event_dev_queue_config(struct rte_eventdev *dev, uint8_t nb_queues)
{
@@ -980,6 +1003,28 @@ rte_event_port_unlink(uint8_t dev_id, uint8_t port_id,
return diag;
}
+int __rte_experimental
+rte_event_port_unlinks_in_progress(uint8_t dev_id, uint8_t port_id)
+{
+ struct rte_eventdev *dev;
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ dev = &rte_eventdevs[dev_id];
+ if (!is_valid_port(dev, port_id)) {
+ RTE_EDEV_LOG_ERR("Invalid port_id=%" PRIu8, port_id);
+ return -EINVAL;
+ }
+
+ /* Return 0 if the PMD does not implement unlinks in progress.
+ * This allows PMDs which handle unlink synchronously to not implement
+ * this function at all.
+ */
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->port_unlinks_in_progress, 0);
+
+ return (*dev->dev_ops->port_unlinks_in_progress)(dev,
+ dev->data->ports[port_id]);
+}
+
int
rte_event_port_links_get(uint8_t dev_id, uint8_t port_id,
uint8_t queues[], uint8_t priorities[])
@@ -1275,6 +1320,15 @@ rte_eventdev_find_free_device_index(void)
return RTE_EVENT_MAX_DEVS;
}
+static uint16_t
+rte_event_tx_adapter_enqueue(__rte_unused void *port,
+ __rte_unused struct rte_event ev[],
+ __rte_unused uint16_t nb_events)
+{
+ rte_errno = ENOTSUP;
+ return 0;
+}
+
struct rte_eventdev *
rte_event_pmd_allocate(const char *name, int socket_id)
{
@@ -1295,6 +1349,8 @@ rte_event_pmd_allocate(const char *name, int socket_id)
eventdev = &rte_eventdevs[dev_id];
+ eventdev->txa_enqueue = rte_event_tx_adapter_enqueue;
+
if (eventdev->data == NULL) {
struct rte_eventdev_data *eventdev_data = NULL;
diff --git a/lib/librte_eventdev/rte_eventdev.h b/lib/librte_eventdev/rte_eventdev.h
index b6fd6ee7..d7eb69d1 100644
--- a/lib/librte_eventdev/rte_eventdev.h
+++ b/lib/librte_eventdev/rte_eventdev.h
@@ -1112,7 +1112,7 @@ struct rte_event {
*
*/
int
-rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint8_t eth_port_id,
+rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
uint32_t *caps);
#define RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT (1ULL << 0)
@@ -1186,6 +1186,32 @@ int __rte_experimental
rte_event_crypto_adapter_caps_get(uint8_t dev_id, uint8_t cdev_id,
uint32_t *caps);
+/* Ethdev Tx adapter capability bitmap flags */
+#define RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT 0x1
+/**< This flag is sent when the PMD supports a packet transmit callback
+ */
+
+/**
+ * Retrieve the event device's eth Tx adapter capabilities
+ *
+ * @param dev_id
+ * The identifier of the device.
+ *
+ * @param eth_port_id
+ * The identifier of the ethernet device.
+ *
+ * @param[out] caps
+ * A pointer to memory filled with eth Tx adapter capabilities.
+ *
+ * @return
+ * - 0: Success, driver provides eth Tx adapter capabilities.
+ * - <0: Error code returned by the driver function.
+ *
+ */
+int __rte_experimental
+rte_event_eth_tx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
+ uint32_t *caps);
+
struct rte_eventdev_ops;
struct rte_eventdev;
@@ -1204,6 +1230,10 @@ typedef uint16_t (*event_dequeue_burst_t)(void *port, struct rte_event ev[],
uint16_t nb_events, uint64_t timeout_ticks);
/**< @internal Dequeue burst of events from port of a device */
+typedef uint16_t (*event_tx_adapter_enqueue)(void *port,
+ struct rte_event ev[], uint16_t nb_events);
+/**< @internal Enqueue burst of events on port of a device */
+
#define RTE_EVENTDEV_NAME_MAX_LEN (64)
/**< @internal Max length of name of event PMD */
@@ -1266,7 +1296,8 @@ struct rte_eventdev {
/**< Pointer to PMD dequeue function. */
event_dequeue_burst_t dequeue_burst;
/**< Pointer to PMD dequeue burst function. */
-
+ event_tx_adapter_enqueue txa_enqueue;
+ /**< Pointer to PMD eth Tx adapter enqueue function. */
struct rte_eventdev_data *data;
/**< Pointer to device data */
struct rte_eventdev_ops *dev_ops;
@@ -1656,12 +1687,13 @@ rte_event_port_link(uint8_t dev_id, uint8_t port_id,
* event port designated by its *port_id* on the event device designated
* by its *dev_id*.
*
- * The unlink establishment shall disable the event port *port_id* from
- * receiving events from the specified event queue *queue_id*
- *
+ * The unlink call issues an async request to disable the event port *port_id*
+ * from receiving events from the specified event queue *queue_id*.
* Event queue(s) to event port unlink establishment can be changed at runtime
* without re-configuring the device.
*
+ * @see rte_event_port_unlinks_in_progress() to poll for completed unlinks.
+ *
* @param dev_id
* The identifier of the device.
*
@@ -1679,22 +1711,48 @@ rte_event_port_link(uint8_t dev_id, uint8_t port_id,
* NULL.
*
* @return
- * The number of unlinks actually established. The return value can be less
+ * The number of unlinks successfully requested. The return value can be less
* than the value of the *nb_unlinks* parameter when the implementation has the
* limitation on specific queue to port unlink establishment or
* if invalid parameters are specified.
* If the return value is less than *nb_unlinks*, the remaining queues at the
- * end of queues[] are not established, and the caller has to take care of them.
+ * end of queues[] are not unlinked, and the caller has to take care of them.
* If return value is less than *nb_unlinks* then implementation shall update
* the rte_errno accordingly, Possible rte_errno values are
* (-EINVAL) Invalid parameter
- *
*/
int
rte_event_port_unlink(uint8_t dev_id, uint8_t port_id,
uint8_t queues[], uint16_t nb_unlinks);
/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Returns the number of unlinks in progress.
+ *
+ * This function provides the application with a method to detect when an
+ * unlink has been completed by the implementation.
+ *
+ * @see rte_event_port_unlink() to issue unlink requests.
+ *
+ * @param dev_id
+ * The indentifier of the device.
+ *
+ * @param port_id
+ * Event port identifier to select port to check for unlinks in progress.
+ *
+ * @return
+ * The number of unlinks that are in progress. A return of zero indicates that
+ * there are no outstanding unlink requests. A positive return value indicates
+ * the number of unlinks that are in progress, but are not yet complete.
+ * A negative return value indicates an error, -EINVAL indicates an invalid
+ * parameter passed for *dev_id* or *port_id*.
+ */
+int __rte_experimental
+rte_event_port_unlinks_in_progress(uint8_t dev_id, uint8_t port_id);
+
+/**
* Retrieve the list of source event queues and its associated service priority
* linked to the destination event port designated by its *port_id*
* on the event device designated by its *dev_id*.
diff --git a/lib/librte_eventdev/rte_eventdev_pmd.h b/lib/librte_eventdev/rte_eventdev_pmd.h
index 3fbb4d2b..1a01326b 100644
--- a/lib/librte_eventdev/rte_eventdev_pmd.h
+++ b/lib/librte_eventdev/rte_eventdev_pmd.h
@@ -87,8 +87,6 @@ struct rte_eventdev_global {
uint8_t nb_devs; /**< Number of devices found */
};
-extern struct rte_eventdev_global *rte_eventdev_globals;
-/** Pointer to global event devices data structure. */
extern struct rte_eventdev *rte_eventdevs;
/** The pool of rte_eventdev structures. */
@@ -333,6 +331,23 @@ typedef int (*eventdev_port_unlink_t)(struct rte_eventdev *dev, void *port,
uint8_t queues[], uint16_t nb_unlinks);
/**
+ * Unlinks in progress. Returns number of unlinks that the PMD is currently
+ * performing, but have not yet been completed.
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @param port
+ * Event port pointer
+ *
+ * @return
+ * Returns the number of in-progress unlinks. Zero is returned if none are
+ * in progress.
+ */
+typedef int (*eventdev_port_unlinks_in_progress_t)(struct rte_eventdev *dev,
+ void *port);
+
+/**
* Converts nanoseconds to *timeout_ticks* value for rte_event_dequeue()
*
* @param dev
@@ -450,7 +465,7 @@ typedef int (*eventdev_eth_rx_adapter_caps_get_t)
const struct rte_eth_dev *eth_dev,
uint32_t *caps);
-struct rte_event_eth_rx_adapter_queue_conf *queue_conf;
+struct rte_event_eth_rx_adapter_queue_conf;
/**
* Retrieve the event device's timer adapter capabilities, as well as the ops
@@ -575,7 +590,7 @@ typedef int (*eventdev_eth_rx_adapter_stop_t)
(const struct rte_eventdev *dev,
const struct rte_eth_dev *eth_dev);
-struct rte_event_eth_rx_adapter_stats *stats;
+struct rte_event_eth_rx_adapter_stats;
/**
* Retrieve ethernet Rx adapter statistics.
@@ -789,6 +804,186 @@ typedef int (*eventdev_crypto_adapter_stats_reset)
(const struct rte_eventdev *dev,
const struct rte_cryptodev *cdev);
+/**
+ * Retrieve the event device's eth Tx adapter capabilities.
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @param eth_dev
+ * Ethernet device pointer
+ *
+ * @param[out] caps
+ * A pointer to memory filled with eth Tx adapter capabilities.
+ *
+ * @return
+ * - 0: Success, driver provides eth Tx adapter capabilities
+ * - <0: Error code returned by the driver function.
+ *
+ */
+typedef int (*eventdev_eth_tx_adapter_caps_get_t)
+ (const struct rte_eventdev *dev,
+ const struct rte_eth_dev *eth_dev,
+ uint32_t *caps);
+
+/**
+ * Create adapter callback.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_create_t)(uint8_t id,
+ const struct rte_eventdev *dev);
+
+/**
+ * Free adapter callback.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_free_t)(uint8_t id,
+ const struct rte_eventdev *dev);
+
+/**
+ * Add a Tx queue to the adapter.
+ * A queue value of -1 is used to indicate all
+ * queues within the device.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @param eth_dev
+ * Ethernet device pointer
+ *
+ * @param tx_queue_id
+ * Transmt queue index
+ *
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_add_t)(
+ uint8_t id,
+ const struct rte_eventdev *dev,
+ const struct rte_eth_dev *eth_dev,
+ int32_t tx_queue_id);
+
+/**
+ * Delete a Tx queue from the adapter.
+ * A queue value of -1 is used to indicate all
+ * queues within the device, that have been added to this
+ * adapter.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @param eth_dev
+ * Ethernet device pointer
+ *
+ * @param tx_queue_id
+ * Transmit queue index
+ *
+ * @return
+ * - 0: Success, Queues deleted successfully.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_del_t)(
+ uint8_t id,
+ const struct rte_eventdev *dev,
+ const struct rte_eth_dev *eth_dev,
+ int32_t tx_queue_id);
+
+/**
+ * Start the adapter.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @return
+ * - 0: Success, Adapter started correctly.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_start_t)(uint8_t id,
+ const struct rte_eventdev *dev);
+
+/**
+ * Stop the adapter.
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @return
+ * - 0: Success.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_stop_t)(uint8_t id,
+ const struct rte_eventdev *dev);
+
+struct rte_event_eth_tx_adapter_stats;
+
+/**
+ * Retrieve statistics for an adapter
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @param [out] stats
+ * A pointer to structure used to retrieve statistics for an adapter
+ *
+ * @return
+ * - 0: Success, statistics retrieved successfully.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_stats_get_t)(
+ uint8_t id,
+ const struct rte_eventdev *dev,
+ struct rte_event_eth_tx_adapter_stats *stats);
+
+/**
+ * Reset statistics for an adapter
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param dev
+ * Event device pointer
+ *
+ * @return
+ * - 0: Success, statistics retrieved successfully.
+ * - <0: Error code on failure.
+ */
+typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
+ const struct rte_eventdev *dev);
+
/** Event device operations function pointer table */
struct rte_eventdev_ops {
eventdev_info_get_t dev_infos_get; /**< Get device info. */
@@ -815,6 +1010,8 @@ struct rte_eventdev_ops {
/**< Link event queues to an event port. */
eventdev_port_unlink_t port_unlink;
/**< Unlink event queues from an event port. */
+ eventdev_port_unlinks_in_progress_t port_unlinks_in_progress;
+ /**< Unlinks in progress on an event port. */
eventdev_dequeue_timeout_ticks_t timeout_ticks;
/**< Converts ns to *timeout_ticks* value for rte_event_dequeue() */
eventdev_dump_t dump;
@@ -862,6 +1059,26 @@ struct rte_eventdev_ops {
eventdev_crypto_adapter_stats_reset crypto_adapter_stats_reset;
/**< Reset crypto stats */
+ eventdev_eth_tx_adapter_caps_get_t eth_tx_adapter_caps_get;
+ /**< Get ethernet Tx adapter capabilities */
+
+ eventdev_eth_tx_adapter_create_t eth_tx_adapter_create;
+ /**< Create adapter callback */
+ eventdev_eth_tx_adapter_free_t eth_tx_adapter_free;
+ /**< Free adapter callback */
+ eventdev_eth_tx_adapter_queue_add_t eth_tx_adapter_queue_add;
+ /**< Add Tx queues to the eth Tx adapter */
+ eventdev_eth_tx_adapter_queue_del_t eth_tx_adapter_queue_del;
+ /**< Delete Tx queues from the eth Tx adapter */
+ eventdev_eth_tx_adapter_start_t eth_tx_adapter_start;
+ /**< Start eth Tx adapter */
+ eventdev_eth_tx_adapter_stop_t eth_tx_adapter_stop;
+ /**< Stop eth Tx adapter */
+ eventdev_eth_tx_adapter_stats_get_t eth_tx_adapter_stats_get;
+ /**< Get eth Tx adapter statistics */
+ eventdev_eth_tx_adapter_stats_reset_t eth_tx_adapter_stats_reset;
+ /**< Reset eth Tx adapter statistics */
+
eventdev_selftest dev_selftest;
/**< Start eventdev Selftest */
diff --git a/lib/librte_eventdev/rte_eventdev_version.map b/lib/librte_eventdev/rte_eventdev_version.map
index 12835e9f..d558d7d5 100644
--- a/lib/librte_eventdev/rte_eventdev_version.map
+++ b/lib/librte_eventdev/rte_eventdev_version.map
@@ -96,6 +96,19 @@ EXPERIMENTAL {
rte_event_crypto_adapter_stats_reset;
rte_event_crypto_adapter_stop;
rte_event_eth_rx_adapter_cb_register;
+ rte_event_port_unlinks_in_progress;
+ rte_event_eth_tx_adapter_caps_get;
+ rte_event_eth_tx_adapter_create;
+ rte_event_eth_tx_adapter_create_ext;
+ rte_event_eth_tx_adapter_event_port_get;
+ rte_event_eth_tx_adapter_free;
+ rte_event_eth_tx_adapter_queue_add;
+ rte_event_eth_tx_adapter_queue_del;
+ rte_event_eth_tx_adapter_service_id_get;
+ rte_event_eth_tx_adapter_start;
+ rte_event_eth_tx_adapter_stats_get;
+ rte_event_eth_tx_adapter_stats_reset;
+ rte_event_eth_tx_adapter_stop;
rte_event_timer_adapter_caps_get;
rte_event_timer_adapter_create;
rte_event_timer_adapter_create_ext;