get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/42452/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 42452,
    "url": "http://patchwork.dpdk.org/api/patches/42452/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/1530859329-160189-3-git-send-email-nikhil.rao@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1530859329-160189-3-git-send-email-nikhil.rao@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1530859329-160189-3-git-send-email-nikhil.rao@intel.com",
    "date": "2018-07-06T06:42:08",
    "name": "[3/4] eventdev: add eth Tx adapter implementation",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "6cfa7ea9b9da65447e6a2b4585a119911deae13c",
    "submitter": {
        "id": 528,
        "url": "http://patchwork.dpdk.org/api/people/528/?format=api",
        "name": "Rao, Nikhil",
        "email": "nikhil.rao@intel.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patchwork.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1530859329-160189-3-git-send-email-nikhil.rao@intel.com/mbox/",
    "series": [
        {
            "id": 447,
            "url": "http://patchwork.dpdk.org/api/series/447/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=447",
            "date": "2018-07-06T06:42:07",
            "name": "[1/4] eventdev: add eth Tx adapter APIs",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/447/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/42452/comments/",
    "check": "fail",
    "checks": "http://patchwork.dpdk.org/api/patches/42452/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 37F811BEC8;\n\tFri,  6 Jul 2018 08:42:29 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby dpdk.org (Postfix) with ESMTP id C50641BEAF\n\tfor <dev@dpdk.org>; Fri,  6 Jul 2018 08:42:24 +0200 (CEST)",
            "from fmsmga008.fm.intel.com ([10.253.24.58])\n\tby fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t05 Jul 2018 23:42:22 -0700",
            "from unknown (HELO localhost.localdomain.localdomain)\n\t([10.224.122.193])\n\tby fmsmga008.fm.intel.com with ESMTP; 05 Jul 2018 23:42:17 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.51,315,1526367600\"; d=\"scan'208\";a=\"53007589\"",
        "From": "Nikhil Rao <nikhil.rao@intel.com>",
        "To": "jerin.jacob@caviumnetworks.com,\n\tolivier.matz@6wind.com",
        "Cc": "nikhil.rao@intel.com,\n\tdev@dpdk.org",
        "Date": "Fri,  6 Jul 2018 12:12:08 +0530",
        "Message-Id": "<1530859329-160189-3-git-send-email-nikhil.rao@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1530859329-160189-1-git-send-email-nikhil.rao@intel.com>",
        "References": "<1530859329-160189-1-git-send-email-nikhil.rao@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 3/4] eventdev: add eth Tx adapter implementation",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch implements the Tx adapter APIs by invoking the\ncorresponding eventdev PMD callbacks and also provides\nthe common rte_service function based implementation when\nthe eventdev PMD support is absent.\n\nSigned-off-by: Nikhil Rao <nikhil.rao@intel.com>\n---\n config/rte_config.h                            |    1 +\n lib/librte_eventdev/rte_event_eth_tx_adapter.c | 1210 ++++++++++++++++++++++++\n config/common_base                             |    2 +-\n lib/librte_eventdev/Makefile                   |    2 +\n lib/librte_eventdev/meson.build                |    6 +-\n lib/librte_eventdev/rte_eventdev_version.map   |   13 +\n 6 files changed, 1231 insertions(+), 3 deletions(-)\n create mode 100644 lib/librte_eventdev/rte_event_eth_tx_adapter.c",
    "diff": "diff --git a/config/rte_config.h b/config/rte_config.h\nindex 0ba0ead..f60cc80 100644\n--- a/config/rte_config.h\n+++ b/config/rte_config.h\n@@ -65,6 +65,7 @@\n #define RTE_EVENT_MAX_QUEUES_PER_DEV 64\n #define RTE_EVENT_TIMER_ADAPTER_NUM_MAX 32\n #define RTE_EVENT_CRYPTO_ADAPTER_MAX_INSTANCE 32\n+#define RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE 32\n \n /* rawdev defines */\n #define RTE_RAWDEV_MAX_DEVS 10\ndiff --git a/lib/librte_eventdev/rte_event_eth_tx_adapter.c b/lib/librte_eventdev/rte_event_eth_tx_adapter.c\nnew file mode 100644\nindex 0000000..b802a13\n--- /dev/null\n+++ b/lib/librte_eventdev/rte_event_eth_tx_adapter.c\n@@ -0,0 +1,1210 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation.\n+ */\n+#include <rte_spinlock.h>\n+#include <rte_service_component.h>\n+#include <rte_ethdev.h>\n+\n+#include \"rte_eventdev_pmd.h\"\n+#include \"rte_event_eth_tx_adapter.h\"\n+\n+#define TXA_BATCH_SIZE\t\t32\n+#define TXA_SERVICE_NAME_LEN\t32\n+#define TXA_MEM_NAME_LEN\t32\n+#define TXA_FLUSH_THRESHOLD\t1024\n+#define TXA_RETRY_CNT\t\t100\n+#define TXA_MAX_NB_TX\t\t128\n+\n+enum txa_pmd_type {\n+\t/* No PMD in use */\n+\tTXA_PMD_NONE = 0,\n+\t/* Event dev PMD */\n+\tTXA_PMD_EVENTDEV,\n+\t/* Service PMD */\n+\tTXA_PMD_SERVICE,\n+};\n+\n+/* Tx retry callback structure */\n+struct txa_retry {\n+\t/* Ethernet port id */\n+\tuint16_t port_id;\n+\t/* Tx queue */\n+\tuint16_t tx_queue;\n+\t/* Adapter ID */\n+\tuint8_t id;\n+};\n+\n+/* Per queue structure */\n+struct txa_service_queue_info {\n+\t/* Queue has been added */\n+\tuint8_t added;\n+\t/* Retry callback argument */\n+\tstruct txa_retry txa_retry;\n+\t/* Tx buffer */\n+\tstruct rte_eth_dev_tx_buffer *tx_buf;\n+};\n+\n+/* PMD private structure */\n+struct txa_service_data {\n+\t/* Event port ID */\n+\tuint8_t port_id;\n+\t/* Per adapter EAL service */\n+\tuint32_t service_id;\n+\t/* Adapter started */\n+\tint started;\n+\t/* Lock to serialize config updates with service function */\n+\trte_spinlock_t tx_lock;\n+\t/* stats */\n+\tstruct rte_event_eth_tx_adapter_stats stats;\n+\t/* Loop count to flush Tx buffers */\n+\tint loop_cnt;\n+};\n+\n+struct txa_dev_ops {\n+\tevent_tx_adapter_enqueue enqueue;\n+\teventdev_eth_tx_adapter_queue_add_t queue_add;\n+\teventdev_eth_tx_adapter_queue_del_t queue_del;\n+\teventdev_eth_tx_adapter_stats_get_t stats_get;\n+\teventdev_eth_tx_adapter_stats_reset_t stats_reset;\n+\teventdev_eth_tx_adapter_init_t init;\n+\teventdev_eth_tx_adapter_free_t free;\n+\teventdev_eth_tx_adapter_start_t start;\n+\teventdev_eth_tx_adapter_stop_t stop;\n+\teventdev_eth_tx_adapter_event_port_get event_port_get;\n+};\n+\n+/* Library private structure */\n+struct txa_internal {\n+\t/* Tx adapter PMD type */\n+\tenum txa_pmd_type pmd_type;\n+\t/* Conf arg must be freed */\n+\tuint8_t conf_free;\n+\t/* Original dev ops from event device */\n+\tstruct txa_dev_ops dev_ops;\n+};\n+\n+#define txa_evdev(t) (&rte_eventdevs[(t)->eventdev_id])\n+\n+#define txa_internal(t) (txa_internals[(t)->id])\n+\n+#define txa_caps_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_caps_get\n+\n+#define txa_enqueue(t) txa_evdev(t)->txa_enqueue\n+\n+#define txa_event_port_get(t) \\\n+\t\t\ttxa_evdev(t)->dev_ops->eth_tx_adapter_event_port_get\n+\n+#define txa_pmd_free(t) txa_evdev(t)->dev_ops->eth_tx_adapter_free\n+\n+#define txa_pmd_init_func(t) txa_evdev(t)->dev_ops->eth_tx_adapter_init\n+\n+#define txa_pmd_none(t) (txa_internal(t)->pmd_type == TXA_PMD_NONE)\n+\n+#define txa_pmd_service(t) (txa_internal(t)->pmd_type == TXA_PMD_SERVICE)\n+\n+#define txa_queue_add(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_add\n+\n+#define txa_queue_del(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_del\n+\n+#define txa_start(t) txa_evdev(t)->dev_ops->eth_tx_adapter_start\n+\n+#define txa_stats_reset(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_reset\n+\n+#define txa_stats_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_get\n+\n+#define txa_stop(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stop\n+\n+struct rte_event_eth_tx_adapters rte_event_eth_tx_adapters;\n+static struct txa_internal **txa_internals;\n+\n+static inline struct txa_service_queue_info *\n+txa_service_queue(struct rte_event_eth_tx_adapter *txa, uint16_t port_id,\n+\t\tuint16_t tx_queue_id)\n+{\n+\tstruct txa_service_queue_info *tqi;\n+\n+\ttqi = txa->txa_ethdev[port_id].queues;\n+\n+\treturn tqi != NULL ? tqi + tx_queue_id : NULL;\n+}\n+\n+static inline int\n+txa_valid_id(uint8_t id)\n+{\n+\treturn id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;\n+}\n+\n+#define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \\\n+do { \\\n+\tif (!txa_valid_id(id)) { \\\n+\t\tRTE_EDEV_LOG_ERR(\"Invalid eth Rx adapter id = %d\", id); \\\n+\t\treturn retval; \\\n+\t} \\\n+} while (0)\n+\n+/* Private definition of tx queue identifier within mbuf */\n+struct txa_mbuf_txq_id {\n+\tuint32_t resvd1;\n+\tuint16_t resvd2;\n+\tuint16_t txq_id;\n+};\n+\n+#define TXA_QID_READ(m)\t\t\t\t\t\t\\\n+({\t\t\t\t\t\t\t\t\\\n+\tconst struct txa_mbuf_txq_id *txa_qid;\t\t\t\\\n+\ttxa_qid = (struct txa_mbuf_txq_id *)(&(m)->hash);\t\\\n+\ttxa_qid->txq_id;\t\t\t\t\t\\\n+})\n+\n+#define TXA_QID_WRITE(m, qid)\t\t\t\t\t\\\n+({\t\t\t\t\t\t\t\t\\\n+\tstruct txa_mbuf_txq_id *txa_qid;\t\t\t\\\n+\ttxa_qid = (struct txa_mbuf_txq_id *)(&(m)->hash);\t\\\n+\ttxa_qid->txq_id\t= qid;\t\t\t\t\t\\\n+})\n+\n+static int\n+txa_service_get_service_id(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tuint32_t *service_id);\n+static int\n+txa_service_event_port_get(struct rte_event_eth_tx_adapter *txa, uint8_t *port);\n+\n+static uint16_t\n+txa_service_enqueue(void *adapter,\n+\t\tconst struct rte_eventdev *dev, void *port,\n+\t\tstruct rte_event ev[], uint16_t nb_events);\n+\n+static int\n+txa_service_pmd_init(struct rte_event_eth_tx_adapter *txa);\n+\n+static int\n+txa_service_pmd_free(struct rte_event_eth_tx_adapter *txa);\n+\n+static int\n+txa_service_queue_add(struct rte_event_eth_tx_adapter *txa,\n+\t\tconst struct rte_eth_dev *dev,\n+\t\tint32_t tx_queue_id);\n+static int\n+txa_service_queue_del(struct rte_event_eth_tx_adapter *txa,\n+\t\tconst struct rte_eth_dev *dev,\n+\t\tint32_t tx_queue_id);\n+\n+static int\n+txa_service_start(struct rte_event_eth_tx_adapter *txa);\n+\n+static int\n+txa_service_stats_get(struct rte_event_eth_tx_adapter *txa,\n+\t\tstruct rte_event_eth_tx_adapter_stats *stats);\n+\n+static int\n+txa_service_stats_reset(struct rte_event_eth_tx_adapter *txa);\n+\n+static int\n+txa_service_stop(struct rte_event_eth_tx_adapter *txa);\n+\n+static struct rte_event_eth_tx_adapter **\n+txa_adapter_init(void)\n+{\n+\tconst char *name = \"rte_event_eth_tx_adapter_array\";\n+\tconst struct rte_memzone *mz;\n+\tunsigned int sz;\n+\n+\tsz = sizeof(void *) *\n+\t    RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;\n+\tsz = RTE_ALIGN(2 * sz, RTE_CACHE_LINE_SIZE);\n+\n+\tmz = rte_memzone_lookup(name);\n+\tif (mz == NULL) {\n+\t\tmz = rte_memzone_reserve_aligned(name, sz, rte_socket_id(), 0,\n+\t\t\t\t\t\t RTE_CACHE_LINE_SIZE);\n+\t\tif (mz == NULL) {\n+\t\t\tRTE_EDEV_LOG_ERR(\"failed to reserve memzone err = %\"\n+\t\t\t\t\tPRId32, rte_errno);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\treturn  mz->addr;\n+}\n+\n+static inline struct rte_event_eth_tx_adapter *\n+txa_id_to_adapter(uint8_t id)\n+{\n+\tstruct rte_event_eth_tx_adapter **p;\n+\n+\tp = rte_event_eth_tx_adapters.data;\n+\tif (!p) {\n+\t\tint n = RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;\n+\t\tp = rte_event_eth_tx_adapters.data = txa_adapter_init();\n+\t\ttxa_internals = (struct txa_internal **)(p + n);\n+\t}\n+\treturn p ? p[id] : NULL;\n+}\n+\n+static void\n+txa_save_ops(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tstruct txa_dev_ops  *ops;\n+\n+\tops = &txa_internal(txa)->dev_ops;\n+\n+\tops->enqueue = txa_enqueue(txa);\n+\tops->queue_add = txa_queue_add(txa);\n+\tops->queue_del = txa_queue_del(txa);\n+\tops->stats_get = txa_stats_get(txa);\n+\tops->stats_reset = txa_stats_reset(txa);\n+\tops->init = txa_pmd_init_func(txa);\n+\tops->free = txa_pmd_free(txa);\n+\tops->start = txa_start(txa);\n+\tops->stop = txa_stop(txa);\n+\tops->event_port_get = txa_event_port_get(txa);\n+}\n+\n+static void\n+txa_restore_ops(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tstruct txa_dev_ops  *ops;\n+\n+\tops = &txa_internal(txa)->dev_ops;\n+\n+\ttxa_enqueue(txa) = ops->enqueue;\n+\ttxa_queue_add(txa) = ops->queue_add;\n+\ttxa_queue_del(txa) = ops->queue_del;\n+\ttxa_stats_get(txa) = ops->stats_get;\n+\ttxa_stats_reset(txa) = ops->stats_reset;\n+\ttxa_pmd_init_func(txa) = ops->init;\n+\ttxa_pmd_free(txa) = ops->free;\n+\ttxa_start(txa) = ops->start;\n+\ttxa_stop(txa) = ops->stop;\n+\ttxa_event_port_get(txa) = ops->event_port_get;\n+}\n+\n+static int\n+txa_default_conf_cb(uint8_t id, uint8_t dev_id,\n+\t\tstruct rte_event_eth_tx_adapter_conf *conf, void *arg)\n+{\n+\tint ret;\n+\tstruct rte_eventdev *dev;\n+\tstruct rte_event_port_conf *pc;\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tstruct rte_event_dev_config dev_conf;\n+\tint started;\n+\tuint8_t port_id;\n+\n+\tpc = arg;\n+\ttxa = txa_id_to_adapter(id);\n+\tdev = txa_evdev(txa);\n+\tdev_conf = dev->data->dev_conf;\n+\n+\tstarted = dev->data->dev_started;\n+\tif (started)\n+\t\trte_event_dev_stop(dev_id);\n+\n+\tport_id = dev_conf.nb_event_ports;\n+\tdev_conf.nb_event_ports += 1;\n+\n+\tret = rte_event_dev_configure(dev_id, &dev_conf);\n+\tif (ret) {\n+\t\tRTE_EDEV_LOG_ERR(\"failed to configure event dev %u\",\n+\t\t\t\t\t\tdev_id);\n+\t\tif (started) {\n+\t\t\tif (rte_event_dev_start(dev_id))\n+\t\t\t\treturn -EIO;\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\tret = rte_event_port_setup(dev_id, port_id, pc);\n+\tif (ret) {\n+\t\tRTE_EDEV_LOG_ERR(\"failed to setup event port %u\\n\",\n+\t\t\t\t\tport_id);\n+\t\tif (started) {\n+\t\t\tif (rte_event_dev_start(dev_id))\n+\t\t\t\treturn -EIO;\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\tconf->event_port_id = port_id;\n+\tconf->max_nb_tx = TXA_MAX_NB_TX;\n+\tif (started)\n+\t\tret = rte_event_dev_start(dev_id);\n+\treturn ret;\n+}\n+\n+static int\n+txa_ethdev_ok(struct rte_event_eth_tx_adapter *txa, uint16_t eth_dev_id)\n+{\n+\treturn eth_dev_id < txa->dev_count;\n+}\n+\n+static int\n+txa_service_queue_array_alloc(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tuint16_t port_id)\n+\n+{\n+\tstruct txa_service_queue_info *tqi;\n+\tuint16_t nb_queue;\n+\n+\tif (txa->txa_ethdev[port_id].queues)\n+\t\treturn 0;\n+\n+\tnb_queue = txa->txa_ethdev[port_id].dev->data->nb_tx_queues;\n+\ttqi = rte_zmalloc_socket(txa->mem_name,\n+\t\t\t\tnb_queue *\n+\t\t\t\tsizeof(struct txa_service_queue_info), 0,\n+\t\t\t\ttxa->socket_id);\n+\tif (tqi == NULL)\n+\t\treturn -ENOMEM;\n+\ttxa->txa_ethdev[port_id].queues = tqi;\n+\treturn 0;\n+}\n+\n+static void\n+txa_service_queue_array_free(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tuint16_t port_id)\n+{\n+\tstruct rte_event_eth_tx_adapter_ethdev *txa_ethdev;\n+\tstruct txa_service_queue_info *tqi;\n+\n+\ttxa_ethdev = &txa->txa_ethdev[port_id];\n+\tif (txa->txa_ethdev == NULL || txa_ethdev->nb_queues != 0)\n+\t\treturn;\n+\n+\ttqi = txa_ethdev->queues;\n+\ttxa_ethdev->queues = NULL;\n+\trte_free(tqi);\n+}\n+\n+static int\n+txa_cap_int_port(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tuint32_t caps = 0;\n+\n+\tif (txa_caps_get(txa))\n+\t\t(txa_caps_get(txa))(txa_evdev(txa), &caps);\n+\treturn !!(caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT);\n+}\n+\n+static int\n+txa_init(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tint ret;\n+\tint txa_service;\n+\tuint16_t i;\n+\tstruct rte_event_eth_tx_adapter_ethdev *txa_ethdev;\n+\n+\tif (txa->txa_ethdev)\n+\t\treturn 0;\n+\n+\ttxa_save_ops(txa);\n+\ttxa_service = 0;\n+\n+\ttxa_ethdev = rte_zmalloc_socket(txa->mem_name,\n+\t\t\t\t\ttxa->dev_count *\n+\t\t\t\t\tsizeof(*txa_ethdev), 0,\n+\t\t\t\t\ttxa->socket_id);\n+\tif (txa_ethdev == NULL) {\n+\t\tRTE_EDEV_LOG_ERR(\"Failed to alloc txa::txa_ethdev \");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tRTE_ETH_FOREACH_DEV(i) {\n+\t\tif (i == txa->dev_count)\n+\t\t\tbreak;\n+\t\ttxa_ethdev[i].dev = &rte_eth_devices[i];\n+\t}\n+\n+\tif (!txa_cap_int_port(txa)) {\n+\t\ttxa_pmd_init_func(txa) = txa_service_pmd_init;\n+\t\ttxa_pmd_free(txa) = txa_service_pmd_free;\n+\t\ttxa_queue_add(txa) = txa_service_queue_add;\n+\t\ttxa_queue_del(txa) = txa_service_queue_del;\n+\t\ttxa_enqueue(txa) = txa_service_enqueue;\n+\t\ttxa_start(txa) = txa_service_start;\n+\t\ttxa_stop(txa) = txa_service_stop;\n+\t\ttxa_stats_get(txa) = txa_service_stats_get;\n+\t\ttxa_stats_reset(txa) = txa_service_stats_reset;\n+\t\ttxa_event_port_get(txa) = txa_service_event_port_get;\n+\t\ttxa_service = 1;\n+\t}\n+\n+\tret = (txa_pmd_init_func(txa)) ?\n+\t\t\ttxa_pmd_init_func(txa)(txa)\n+\t\t\t: 0;\n+\n+\ttxa_internal(txa)->pmd_type = TXA_PMD_NONE;\n+\tif (ret == 0) {\n+\t\ttxa_internal(txa)->pmd_type = txa_service ?\n+\t\t\t\t\tTXA_PMD_SERVICE :\n+\t\t\t\t\tTXA_PMD_EVENTDEV;\n+\t\ttxa->txa_ethdev = txa_ethdev;\n+\t} else {\n+\t\trte_free(txa_ethdev);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static void\n+txa_service_tx(struct rte_event_eth_tx_adapter *txa, struct rte_event *ev,\n+\tuint32_t n)\n+{\n+\tuint32_t i;\n+\tuint16_t nb_tx;\n+\tstruct txa_service_data *data;\n+\tstruct rte_event_eth_tx_adapter_ethdev *tdi;\n+\tstruct rte_event_eth_tx_adapter_stats *stats;\n+\n+\ttdi = txa->txa_ethdev;\n+\tdata = txa->dev_private;\n+\tstats = &data->stats;\n+\n+\tnb_tx = 0;\n+\tfor (i = 0; i < n; i++) {\n+\t\tstruct rte_mbuf *m;\n+\t\tuint16_t port;\n+\t\tuint16_t queue;\n+\t\tstruct txa_service_queue_info *tqi;\n+\n+\t\tm = ev[i].mbuf;\n+\t\tport = m->port;\n+\t\tqueue = TXA_QID_READ(m);\n+\n+\t\ttqi = txa_service_queue(txa, port, queue);\n+\t\tif (unlikely(tdi == NULL ||\n+\t\t\ttdi[port].nb_queues == 0 || !tqi->added)) {\n+\t\t\trte_pktmbuf_free(m);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tnb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf, m);\n+\t}\n+\n+\tstats->tx_packets += nb_tx;\n+}\n+\n+static int32_t\n+txa_service_func(void *args)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa = args;\n+\tuint8_t dev_id;\n+\tuint8_t port;\n+\tuint16_t n;\n+\tuint32_t nb_tx, max_nb_tx;\n+\tstruct rte_event ev[TXA_BATCH_SIZE];\n+\tstruct txa_service_data *data;\n+\n+\tdev_id = txa->eventdev_id;\n+\tmax_nb_tx = txa->max_nb_tx;\n+\tdata = txa->dev_private;\n+\tport = data->port_id;\n+\n+\tif (!rte_spinlock_trylock(&txa->tx_lock))\n+\t\treturn 0;\n+\n+\tfor (nb_tx = 0; nb_tx < max_nb_tx; nb_tx += n) {\n+\n+\t\tn = rte_event_dequeue_burst(dev_id, port, ev, RTE_DIM(ev), 0);\n+\t\tif (!n)\n+\t\t\tbreak;\n+\t\ttxa_service_tx(txa, ev, n);\n+\t}\n+\n+\tif ((data->loop_cnt++ & (TXA_FLUSH_THRESHOLD - 1)) == 0) {\n+\n+\t\tstruct rte_event_eth_tx_adapter_ethdev *tdi;\n+\t\tstruct txa_service_queue_info *tqi;\n+\t\tstruct rte_eth_dev *dev;\n+\t\tuint16_t i;\n+\n+\t\ttdi = txa->txa_ethdev;\n+\t\tnb_tx = 0;\n+\n+\t\tRTE_ETH_FOREACH_DEV(i) {\n+\t\t\tuint16_t q;\n+\n+\t\t\tif (i == txa->dev_count)\n+\t\t\t\tbreak;\n+\n+\t\t\tdev = tdi[i].dev;\n+\t\t\tif (tdi[i].nb_queues == 0)\n+\t\t\t\tcontinue;\n+\t\t\tfor (q = 0; q < dev->data->nb_tx_queues; q++) {\n+\n+\t\t\t\ttqi = txa_service_queue(txa, i, q);\n+\t\t\t\tif (!tqi->added)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tnb_tx += rte_eth_tx_buffer_flush(i, q,\n+\t\t\t\t\t\t\ttqi->tx_buf);\n+\t\t\t}\n+\t\t}\n+\n+\t\tdata->stats.tx_packets += nb_tx;\n+\t}\n+\trte_spinlock_unlock(&txa->tx_lock);\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_init(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tint ret;\n+\tstruct rte_service_spec service;\n+\tstruct rte_event_eth_tx_adapter_conf conf;\n+\tstruct txa_service_data *data;\n+\n+\tdata = txa->dev_private;\n+\n+\tmemset(&service, 0, sizeof(service));\n+\tsnprintf(service.name, TXA_SERVICE_NAME_LEN,\n+\t\t\"rte_event_eth_txa_%d\", txa->id);\n+\tservice.socket_id = txa->socket_id;\n+\tservice.callback = txa_service_func;\n+\tservice.callback_userdata = txa;\n+\t/* Service function handles locking for queue add/del updates */\n+\tservice.capabilities = RTE_SERVICE_CAP_MT_SAFE;\n+\tret = rte_service_component_register(&service, &data->service_id);\n+\tif (ret) {\n+\t\tRTE_EDEV_LOG_ERR(\"failed to register service %s err = %\" PRId32,\n+\t\t\tservice.name, ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = txa->conf_cb(txa->id, txa->eventdev_id, &conf, txa->conf_arg);\n+\tif (ret) {\n+\t\trte_service_component_unregister(data->service_id);\n+\t\treturn ret;\n+\t}\n+\n+\tdata->port_id = conf.event_port_id;\n+\ttxa->max_nb_tx = conf.max_nb_tx;\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_pmd_free(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tstruct txa_service_data *data;\n+\n+\tdata = txa->dev_private;\n+\n+\tif (txa->nb_queues != 0)\n+\t\treturn 0;\n+\n+\tif (txa_pmd_service(txa)) {\n+\t\trte_service_component_runstate_set(data->service_id, 0);\n+\t\twhile (rte_service_may_be_active(data->service_id))\n+\t\t\trte_pause();\n+\t\trte_service_component_unregister(data->service_id);\n+\t}\n+\n+\trte_free(txa->dev_private);\n+\ttxa->dev_private = NULL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_pmd_init(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tint ret;\n+\tstruct txa_service_data *data;\n+\n+\tdata = rte_zmalloc_socket(txa->mem_name,\n+\t\t\t\tsizeof(*data), 0,\n+\t\t\t\ttxa->socket_id);\n+\tif (!data) {\n+\t\tRTE_EDEV_LOG_ERR(\"Failed to alloc PMD private data\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\ttxa->dev_private = data;\n+\tret = txa_service_init(txa);\n+\tif (ret) {\n+\t\trte_free(data);\n+\t\ttxa->dev_private = NULL;\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_ctrl(struct rte_event_eth_tx_adapter *txa, int start)\n+{\n+\tint ret;\n+\tstruct txa_service_data *data = txa->dev_private;\n+\n+\tret = rte_service_runstate_set(data->service_id, start);\n+\tif (ret == 0 && !start) {\n+\t\twhile (rte_service_may_be_active(data->service_id))\n+\t\t\trte_pause();\n+\t}\n+\treturn ret;\n+}\n+\n+static int\n+txa_service_start(struct rte_event_eth_tx_adapter *txa)\n+{\n+\treturn txa_service_ctrl(txa, 1);\n+}\n+\n+static int\n+txa_service_stop(struct rte_event_eth_tx_adapter *txa)\n+{\n+\treturn txa_service_ctrl(txa, 0);\n+}\n+\n+static int\n+txa_service_event_port_get(struct rte_event_eth_tx_adapter *txa, uint8_t *port)\n+{\n+\tstruct txa_service_data *data = txa->dev_private;\n+\n+\t*port = data->port_id;\n+\treturn 0;\n+}\n+\n+static void\n+txa_service_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,\n+\t\t\tvoid *userdata)\n+{\n+\tstruct txa_retry *tr;\n+\tstruct txa_service_data *data;\n+\tstruct rte_event_eth_tx_adapter_stats *stats;\n+\tuint16_t sent = 0;\n+\tunsigned int retry = 0;\n+\tuint16_t i, n;\n+\n+\ttr = (struct txa_retry *)(uintptr_t)userdata;\n+\tdata = txa_id_to_adapter(tr->id)->dev_private;\n+\tstats = &data->stats;\n+\n+\tdo {\n+\t\tn = rte_eth_tx_burst(tr->port_id, tr->tx_queue,\n+\t\t\t       &pkts[sent], unsent - sent);\n+\n+\t\tsent += n;\n+\t} while (sent != unsent && retry++ < TXA_RETRY_CNT);\n+\n+\tfor (i = sent; i < unsent; i++)\n+\t\trte_pktmbuf_free(pkts[i]);\n+\n+\tstats->tx_retry += retry;\n+\tstats->tx_packets += sent;\n+\tstats->tx_dropped += unsent - sent;\n+}\n+\n+static struct rte_eth_dev_tx_buffer *\n+txa_service_tx_buf_alloc(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tconst struct rte_eth_dev *dev)\n+{\n+\tstruct rte_eth_dev_tx_buffer *tb;\n+\tuint16_t port_id;\n+\n+\tport_id = dev->data->port_id;\n+\ttb = rte_zmalloc_socket(txa->mem_name,\n+\t\t\t\tRTE_ETH_TX_BUFFER_SIZE(TXA_BATCH_SIZE),\n+\t\t\t\t0,\n+\t\t\t\trte_eth_dev_socket_id(port_id));\n+\tif (tb == NULL)\n+\t\tRTE_EDEV_LOG_ERR(\"Failed to allocate memory for tx buffer\");\n+\treturn tb;\n+}\n+\n+static int\n+txa_service_queue_del(struct rte_event_eth_tx_adapter *txa,\n+\t\tconst struct rte_eth_dev *dev,\n+\t\tint32_t tx_queue_id)\n+{\n+\tstruct txa_service_queue_info *tqi;\n+\tstruct rte_eth_dev_tx_buffer *tb;\n+\tuint16_t port_id;\n+\n+\tif (tx_queue_id == -1) {\n+\t\tuint16_t i;\n+\t\tint ret;\n+\n+\t\tfor (i = 0; i < dev->data->nb_tx_queues; i++) {\n+\t\t\tret = txa_service_queue_del(txa, dev, i);\n+\t\t\tif (ret != 0)\n+\t\t\t\tbreak;\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\tport_id = dev->data->port_id;\n+\ttqi = txa_service_queue(txa, port_id, tx_queue_id);\n+\tif (!tqi || !tqi->added)\n+\t\treturn 0;\n+\n+\ttb = tqi->tx_buf;\n+\n+\ttqi->added = 0;\n+\ttqi->tx_buf = NULL;\n+\trte_free(tb);\n+\ttxa->nb_queues--;\n+\ttxa->txa_ethdev[port_id].nb_queues--;\n+\n+\ttxa_service_queue_array_free(txa, port_id);\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_queue_added(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tconst struct rte_eth_dev *dev,\n+\t\t\tuint16_t tx_queue_id)\n+{\n+\tstruct txa_service_queue_info *tqi;\n+\n+\ttqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);\n+\treturn tqi && tqi->added;\n+}\n+\n+static int\n+txa_service_queue_add(struct rte_event_eth_tx_adapter *txa,\n+\t\tconst struct rte_eth_dev *dev,\n+\t\tint32_t tx_queue_id)\n+{\n+\tstruct txa_service_data *data = txa->dev_private;\n+\tstruct rte_event_eth_tx_adapter_ethdev *tdi;\n+\tstruct txa_service_queue_info *tqi;\n+\tstruct rte_eth_dev_tx_buffer *tb;\n+\tstruct txa_retry *txa_retry;\n+\tint ret;\n+\n+\tret = txa_service_queue_array_alloc(txa, dev->data->port_id);\n+\tif (ret)\n+\t\treturn ret;\n+\ttdi = &txa->txa_ethdev[dev->data->port_id];\n+\tif (tx_queue_id == -1) {\n+\t\tint nb_queues = dev->data->nb_tx_queues - tdi->nb_queues;\n+\t\tuint16_t i, j;\n+\t\tuint16_t *qdone;\n+\n+\t\tqdone = rte_zmalloc(txa->mem_name,\n+\t\t\t\tnb_queues * sizeof(*qdone), 0);\n+\t\tj = 0;\n+\t\tfor (i = 0; i < nb_queues; i++) {\n+\t\t\tif (txa_service_queue_added(txa, dev, i))\n+\t\t\t\tcontinue;\n+\t\t\tret = txa_service_queue_add(txa, dev, i);\n+\t\t\tif (ret == 0)\n+\t\t\t\tqdone[j++] = i;\n+\t\t\telse\n+\t\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (i != nb_queues) {\n+\t\t\tfor (i = 0; i < j; i++)\n+\t\t\t\ttxa_service_queue_del(txa, dev, qdone[i]);\n+\t\t}\n+\t\trte_free(qdone);\n+\t\treturn ret;\n+\t}\n+\n+\tif (txa_service_queue_added(txa, dev, tx_queue_id))\n+\t\treturn 0;\n+\n+\ttb = txa_service_tx_buf_alloc(txa, dev);\n+\tif (tb == NULL)\n+\t\treturn -ENOMEM;\n+\n+\ttqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);\n+\n+\ttxa_retry = &tqi->txa_retry;\n+\ttxa_retry->id = txa->id;\n+\ttxa_retry->port_id = dev->data->port_id;\n+\ttxa_retry->tx_queue = tx_queue_id;\n+\n+\trte_eth_tx_buffer_init(tb, TXA_BATCH_SIZE);\n+\trte_eth_tx_buffer_set_err_callback(tb,\n+\t\ttxa_service_buffer_retry, txa_retry);\n+\n+\ttqi->tx_buf = tb;\n+\ttqi->added = 1;\n+\trte_service_component_runstate_set(data->service_id, 1);\n+\ttdi->nb_queues++;\n+\ttxa->nb_queues++;\n+\treturn 0;\n+}\n+\n+static uint16_t\n+txa_service_enqueue(void *adapter,\n+\t\tconst struct rte_eventdev *dev, void *port,\n+\t\tstruct rte_event ev[], uint16_t nb_events)\n+{\n+\tRTE_SET_USED(adapter);\n+\tRTE_SET_USED(dev);\n+\tRTE_SET_USED(port);\n+\tRTE_SET_USED(ev);\n+\tRTE_SET_USED(nb_events);\n+\n+\tRTE_EDEV_LOG_ERR(\"Service adapter does not support enqueue callback\");\n+\trte_errno = ENOTSUP;\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_stats_get(struct rte_event_eth_tx_adapter *txa,\n+\t\tstruct rte_event_eth_tx_adapter_stats *stats)\n+{\n+\tstruct txa_service_data *data;\n+\n+\tdata = txa->dev_private;\n+\t*stats = data->stats;\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_get_service_id(struct rte_event_eth_tx_adapter *txa,\n+\t\t\tuint32_t *service_id)\n+{\n+\tstruct txa_service_data *data;\n+\n+\tdata = txa->dev_private;\n+\tif (data == NULL)\n+\t\treturn -ESRCH;\n+\n+\t*service_id = data->service_id;\n+\treturn 0;\n+}\n+\n+static int\n+txa_service_stats_reset(struct rte_event_eth_tx_adapter *txa)\n+{\n+\tstruct txa_service_data *data;\n+\n+\tdata = txa->dev_private;\n+\n+\tmemset(&data->stats, 0, sizeof(data->stats));\n+\treturn 0;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,\n+\t\t\t\tstruct rte_event_port_conf *port_conf)\n+{\n+\tstruct rte_event_port_conf *cb_conf;\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tint ret;\n+\n+\tif (port_conf == NULL)\n+\t\treturn -EINVAL;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa != NULL) {\n+\t\tRTE_EDEV_LOG_ERR(\"Eth Tx adapter exists id = %\" PRIu8, id);\n+\t\treturn -EEXIST;\n+\t}\n+\n+\tcb_conf = rte_malloc(NULL, sizeof(*cb_conf), 0);\n+\tif (cb_conf == NULL)\n+\t\treturn -ENOMEM;\n+\t*cb_conf = *port_conf;\n+\tret = rte_event_eth_tx_adapter_create_ext(id, dev_id,\n+\t\t\t\t\t\ttxa_default_conf_cb,\n+\t\t\t\t\t\tcb_conf);\n+\tif (ret) {\n+\t\trte_free(cb_conf);\n+\t\treturn ret;\n+\t}\n+\n+\ttxa = txa_id_to_adapter(id);\n+\ttxa_internal(txa)->conf_free = 1;\n+\treturn ret;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,\n+\t\t\t\trte_event_eth_tx_adapter_conf_cb conf_cb,\n+\t\t\t\tvoid *conf_arg)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tstruct txa_internal *internal;\n+\tint socket_id;\n+\tchar mem_name[TXA_SERVICE_NAME_LEN];\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\tRTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);\n+\tif (conf_cb == NULL)\n+\t\treturn -EINVAL;\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa != NULL) {\n+\t\tRTE_EDEV_LOG_ERR(\"Eth Tx adapter exists id = %\" PRIu8, id);\n+\t\treturn -EEXIST;\n+\t}\n+\n+\tsocket_id = rte_event_dev_socket_id(dev_id);\n+\tsnprintf(mem_name, TXA_MEM_NAME_LEN,\n+\t\t\"rte_event_eth_txa_%d\",\n+\t\tid);\n+\n+\ttxa = rte_zmalloc_socket(mem_name,\n+\t\t\t\tsizeof(*txa),\n+\t\t\t\tRTE_CACHE_LINE_SIZE, socket_id);\n+\tif (txa == NULL) {\n+\t\tRTE_EDEV_LOG_ERR(\"failed to get mem for tx adapter\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tinternal = rte_zmalloc_socket(mem_name,\n+\t\t\t\tsizeof(*internal),\n+\t\t\t\tRTE_CACHE_LINE_SIZE, socket_id);\n+\tif (internal == NULL) {\n+\t\tRTE_EDEV_LOG_ERR(\"failed to get mem for tx adapter internal\"\n+\t\t\t\" data\");\n+\t\trte_free(txa);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\ttxa->id = id;\n+\ttxa->eventdev_id = dev_id;\n+\ttxa->socket_id = socket_id;\n+\tstrncpy(txa->mem_name, mem_name, TXA_SERVICE_NAME_LEN);\n+\ttxa->conf_cb = conf_cb;\n+\ttxa->conf_arg = conf_arg;\n+\trte_spinlock_init(&txa->tx_lock);\n+\trte_event_eth_tx_adapters.data[id] = txa;\n+\ttxa_internals[id] = internal;\n+\treturn 0;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\treturn txa_event_port_get(txa) ?\n+\t\t\ttxa_event_port_get(txa)(txa, event_port_id) :\n+\t\t\t-ENOTSUP;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_free(uint8_t id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tstruct txa_internal *internal;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa->nb_queues) {\n+\t\tRTE_EDEV_LOG_ERR(\"%\" PRIu16 \" Tx queues not deleted\",\n+\t\t\t\ttxa->nb_queues);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tinternal = txa_internal(txa);\n+\ttxa_restore_ops(txa);\n+\tif (internal->conf_free)\n+\t\trte_free(txa->conf_arg);\n+\trte_free(txa);\n+\trte_free(internal);\n+\trte_event_eth_tx_adapters.data[id] = NULL;\n+\ttxa_internals[id] = NULL;\n+\treturn 0;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_queue_add(uint8_t id,\n+\t\t\t\tuint16_t eth_dev_id,\n+\t\t\t\tint32_t queue)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tint ret;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa->dev_count == 0)\n+\t\ttxa->dev_count = rte_eth_dev_count_total();\n+\n+\tif (txa->dev_count == 0)\n+\t\treturn -EINVAL;\n+\n+\tif (!txa_ethdev_ok(txa, eth_dev_id)) {\n+\t\tRTE_EDEV_LOG_ERR(\"Hot plugged device is unsupported eth port %\"\n+\t\t\t\tPRIu16, eth_dev_id);\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (queue != -1 && (uint16_t)queue >=\n+\t\t\trte_eth_devices[eth_dev_id].data->nb_rx_queues) {\n+\t\tRTE_EDEV_LOG_ERR(\"Invalid rx queue_id %\" PRIu16,\n+\t\t\t\t(uint16_t)queue);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = txa_init(txa);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\trte_spinlock_lock(&txa->tx_lock);\n+\tret =  txa_queue_add(txa) ?\n+\t\t\ttxa_queue_add(txa)(txa,\n+\t\t\t\t&rte_eth_devices[eth_dev_id],\n+\t\t\t\tqueue)\n+\t\t\t: 0;\n+\n+\tif (txa->nb_queues == 0) {\n+\t\ttxa_pmd_free(txa)(txa);\n+\t\ttxa_internal(txa)->pmd_type = TXA_PMD_NONE;\n+\t}\n+\n+\trte_spinlock_unlock(&txa->tx_lock);\n+\treturn ret;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_queue_del(uint8_t id,\n+\t\t\t\t\tuint16_t eth_dev_id,\n+\t\t\t\t\tint32_t queue)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\tint ret;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (queue != -1 && (uint16_t)queue >=\n+\t\t\trte_eth_devices[eth_dev_id].data->nb_rx_queues) {\n+\t\tRTE_EDEV_LOG_ERR(\"Invalid rx queue_id %\" PRIu16,\n+\t\t\t\t(uint16_t)queue);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (txa_pmd_none(txa))\n+\t\treturn 0;\n+\n+\trte_spinlock_lock(&txa->tx_lock);\n+\n+\tret =  txa_queue_del(txa) ?\n+\t\t\ttxa_queue_del(txa)(txa,\n+\t\t\t\t\t&rte_eth_devices[eth_dev_id],\n+\t\t\t\t\tqueue)\n+\t\t\t\t\t: 0;\n+\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\tif (txa->nb_queues == 0) {\n+\t\ttxa_pmd_free(txa)(txa);\n+\t\ttxa_internal(txa)->pmd_type = TXA_PMD_NONE;\n+\t}\n+\n+\trte_spinlock_unlock(&txa->tx_lock);\n+\treturn 0;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL || service_id == NULL)\n+\t\treturn -EINVAL;\n+\n+\treturn txa_pmd_service(txa) ?\n+\t\t\t\ttxa_service_get_service_id(txa, service_id) :\n+\t\t\t\t-ESRCH;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_start(uint8_t id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa_pmd_none(txa))\n+\t\treturn 0;\n+\n+\treturn (txa_start(txa)) ? txa_start(txa)(txa) : 0;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_stats_get(uint8_t id,\n+\t\t\t\tstruct rte_event_eth_tx_adapter_stats *stats)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL || stats == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa_pmd_none(txa)) {\n+\t\tmemset(stats, 0, sizeof(*stats));\n+\t\treturn 0;\n+\t}\n+\n+\treturn txa_stats_get(txa) ?\n+\t\ttxa_stats_get(txa)(txa, stats) :\n+\t\t-ENOTSUP;\n+}\n+\n+int __rte_experimental\n+rte_event_eth_tx_adapter_stats_reset(uint8_t id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa_pmd_none(txa))\n+\t\treturn 0;\n+\n+\treturn txa_stats_reset(txa) ?\n+\t\ttxa_stats_reset(txa)(txa) : -ENOTSUP;\n+}\n+\n+int rte_event_eth_tx_adapter_stop(uint8_t id)\n+{\n+\tstruct rte_event_eth_tx_adapter *txa;\n+\n+\tRTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);\n+\ttxa = txa_id_to_adapter(id);\n+\tif (txa == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (txa_pmd_none(txa))\n+\t\treturn 0;\n+\n+\treturn (txa_stop(txa)) ? txa_stop(txa)(txa) : 0;\n+}\n+\n+void\n+rte_event_eth_tx_adapter_txq_set(struct rte_mbuf *pkt, uint16_t txq_id)\n+{\n+\tTXA_QID_WRITE(pkt, txq_id);\n+}\ndiff --git a/config/common_base b/config/common_base\nindex 721e59b..ea5b06f 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -593,7 +593,7 @@ CONFIG_RTE_EVENT_MAX_DEVS=16\n CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64\n CONFIG_RTE_EVENT_TIMER_ADAPTER_NUM_MAX=32\n CONFIG_RTE_EVENT_CRYPTO_ADAPTER_MAX_INSTANCE=32\n-\n+CONFIG_RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE=32\n #\n # Compile PMD for skeleton event device\n #\ndiff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile\nindex b3e2546..0c077f6 100644\n--- a/lib/librte_eventdev/Makefile\n+++ b/lib/librte_eventdev/Makefile\n@@ -23,6 +23,7 @@ SRCS-y += rte_event_ring.c\n SRCS-y += rte_event_eth_rx_adapter.c\n SRCS-y += rte_event_timer_adapter.c\n SRCS-y += rte_event_crypto_adapter.c\n+SRCS-y += rte_event_eth_tx_adapter.c\n \n # export include files\n SYMLINK-y-include += rte_eventdev.h\n@@ -34,6 +35,7 @@ SYMLINK-y-include += rte_event_eth_rx_adapter.h\n SYMLINK-y-include += rte_event_timer_adapter.h\n SYMLINK-y-include += rte_event_timer_adapter_pmd.h\n SYMLINK-y-include += rte_event_crypto_adapter.h\n+SYMLINK-y-include += rte_event_eth_tx_adapter.h\n \n # versioning export map\n EXPORT_MAP := rte_eventdev_version.map\ndiff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build\nindex bd138bd..d885743 100644\n--- a/lib/librte_eventdev/meson.build\n+++ b/lib/librte_eventdev/meson.build\n@@ -7,7 +7,8 @@ sources = files('rte_eventdev.c',\n \t\t'rte_event_ring.c',\n \t\t'rte_event_eth_rx_adapter.c',\n \t\t'rte_event_timer_adapter.c',\n-\t\t'rte_event_crypto_adapter.c')\n+\t\t'rte_event_crypto_adapter.c',\n+\t\t'rte_event_eth_tx_adapter.c')\n headers = files('rte_eventdev.h',\n \t\t'rte_eventdev_pmd.h',\n \t\t'rte_eventdev_pmd_pci.h',\n@@ -16,5 +17,6 @@ headers = files('rte_eventdev.h',\n \t\t'rte_event_eth_rx_adapter.h',\n \t\t'rte_event_timer_adapter.h',\n \t\t'rte_event_timer_adapter_pmd.h',\n-\t\t'rte_event_crypto_adapter.h')\n+\t\t'rte_event_crypto_adapter.h'\n+\t\t'rte_event_eth_tx_adapter.h')\n deps += ['ring', 'ethdev', 'hash', 'mempool', 'mbuf', 'timer', 'cryptodev']\ndiff --git a/lib/librte_eventdev/rte_eventdev_version.map b/lib/librte_eventdev/rte_eventdev_version.map\nindex c3f18d6..8284c7c 100644\n--- a/lib/librte_eventdev/rte_eventdev_version.map\n+++ b/lib/librte_eventdev/rte_eventdev_version.map\n@@ -109,4 +109,17 @@ EXPERIMENTAL {\n \trte_event_crypto_adapter_stats_get;\n \trte_event_crypto_adapter_stats_reset;\n \trte_event_crypto_adapter_stop;\n+\trte_event_eth_tx_adapter_caps_get;\n+\trte_event_eth_tx_adapter_create;\n+\trte_event_eth_tx_adapter_create_ext;\n+\trte_event_eth_tx_adapter_event_port_get;\n+\trte_event_eth_tx_adapter_free;\n+\trte_event_eth_tx_adapter_queue_add;\n+\trte_event_eth_tx_adapter_queue_del;\n+\trte_event_eth_tx_adapter_service_id_get;\n+\trte_event_eth_tx_adapter_start;\n+\trte_event_eth_tx_adapter_stats_get;\n+\trte_event_eth_tx_adapter_stats_reset;\n+\trte_event_eth_tx_adapter_stop;\n+\trte_event_eth_tx_adapter_txq_set;\n };\n",
    "prefixes": [
        "3/4"
    ]
}