get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131069,
    "url": "https://patches.dpdk.org/api/patches/131069/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230901093514.224824-25-wanry@3snic.com/",
    "project": {
        "id": 1,
        "url": "https://patches.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": "<20230901093514.224824-25-wanry@3snic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230901093514.224824-25-wanry@3snic.com",
    "date": "2023-09-01T09:35:06",
    "name": "[v4,24/32] net/sssnic: support Tx packet burst",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1d7838398c54dd398f1d464aed77bfb1d4d1d93e",
    "submitter": {
        "id": 3119,
        "url": "https://patches.dpdk.org/api/people/3119/?format=api",
        "name": "Renyong Wan",
        "email": "wanry@3snic.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230901093514.224824-25-wanry@3snic.com/mbox/",
    "series": [
        {
            "id": 29401,
            "url": "https://patches.dpdk.org/api/series/29401/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29401",
            "date": "2023-09-01T09:34:43",
            "name": "Introduce sssnic PMD for 3SNIC's 9x0 serials Ethernet adapters",
            "version": 4,
            "mbox": "https://patches.dpdk.org/series/29401/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/131069/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/131069/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 1D7D44221E;\n\tFri,  1 Sep 2023 11:39:07 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 989E240E54;\n\tFri,  1 Sep 2023 11:36:18 +0200 (CEST)",
            "from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186])\n by mails.dpdk.org (Postfix) with ESMTP id 3F2DF40689\n for <dev@dpdk.org>; Fri,  1 Sep 2023 11:36:10 +0200 (CEST)",
            "from V12DG1MBS03.ramaxel.local ([172.26.18.33])\n by VLXDG1SPAM1.ramaxel.com with ESMTP id 3819ZXv6069868;\n Fri, 1 Sep 2023 17:35:33 +0800 (GMT-8)\n (envelope-from wanry@3snic.com)",
            "from localhost.localdomain (10.64.136.151) by\n V12DG1MBS03.ramaxel.local (172.26.18.33) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id\n 15.1.2375.17; Fri, 1 Sep 2023 17:35:32 +0800"
        ],
        "From": "<wanry@3snic.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<ferruh.yigit@amd.com>, Renyong Wan <wanry@3snic.com>, Steven Song\n <steven.song@3snic.com>",
        "Subject": "[PATCH v4 24/32] net/sssnic: support Tx packet burst",
        "Date": "Fri, 1 Sep 2023 17:35:06 +0800",
        "Message-ID": "<20230901093514.224824-25-wanry@3snic.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230901093514.224824-1-wanry@3snic.com>",
        "References": "<20230901093514.224824-1-wanry@3snic.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "7bit",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.64.136.151]",
        "X-ClientProxiedBy": "V12DG1MBS03.ramaxel.local (172.26.18.33) To\n V12DG1MBS03.ramaxel.local (172.26.18.33)",
        "X-DNSRBL": "",
        "X-SPAM-SOURCE-CHECK": "pass",
        "X-MAIL": "VLXDG1SPAM1.ramaxel.com 3819ZXv6069868",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "From: Renyong Wan <wanry@3snic.com>\n\nSigned-off-by: Steven Song <steven.song@3snic.com>\nSigned-off-by: Renyong Wan <wanry@3snic.com>\n---\nv2:\n* Fixed wrong format of printing uint64_t.\n---\n doc/guides/nics/features/sssnic.ini   |   5 +\n drivers/net/sssnic/sssnic_ethdev.c    |   1 +\n drivers/net/sssnic/sssnic_ethdev_tx.c | 404 ++++++++++++++++++++++++++\n drivers/net/sssnic/sssnic_ethdev_tx.h |   2 +\n 4 files changed, 412 insertions(+)",
    "diff": "diff --git a/doc/guides/nics/features/sssnic.ini b/doc/guides/nics/features/sssnic.ini\nindex 320ac4533d..7e6b70684a 100644\n--- a/doc/guides/nics/features/sssnic.ini\n+++ b/doc/guides/nics/features/sssnic.ini\n@@ -9,11 +9,16 @@ Link status event    = Y\n Queue start/stop     = Y\n Rx interrupt         = Y\n Scattered Rx         = Y\n+TSO                  = Y\n LRO                  = Y\n Promiscuous mode     = Y\n Allmulticast mode    = Y\n Unicast MAC filter   = Y\n Multicast MAC filter = Y\n+L3 checksum offload  = Y\n+L4 checksum offload  = Y\n+Inner L3 checksum    = Y\n+Inner L4 checksum    = Y\n Basic stats          = Y\n Extended stats       = Y\n Stats per queue      = Y\ndiff --git a/drivers/net/sssnic/sssnic_ethdev.c b/drivers/net/sssnic/sssnic_ethdev.c\nindex 021fabcbe5..328fb85d30 100644\n--- a/drivers/net/sssnic/sssnic_ethdev.c\n+++ b/drivers/net/sssnic/sssnic_ethdev.c\n@@ -770,6 +770,7 @@ sssnic_ethdev_init(struct rte_eth_dev *ethdev)\n \t\treturn 0;\n \n \tethdev->rx_pkt_burst = sssnic_ethdev_rx_pkt_burst;\n+\tethdev->tx_pkt_burst = sssnic_ethdev_tx_pkt_burst;\n \n \tnetdev = SSSNIC_ETHDEV_PRIVATE(ethdev);\n \tpci_dev = RTE_ETH_DEV_TO_PCI(ethdev);\ndiff --git a/drivers/net/sssnic/sssnic_ethdev_tx.c b/drivers/net/sssnic/sssnic_ethdev_tx.c\nindex d167e3f307..533befb6ea 100644\n--- a/drivers/net/sssnic/sssnic_ethdev_tx.c\n+++ b/drivers/net/sssnic/sssnic_ethdev_tx.c\n@@ -171,6 +171,17 @@ enum sssnic_ethdev_txq_entry_type {\n \tSSSNIC_ETHDEV_TXQ_ENTRY_EXTEND = 1,\n };\n \n+struct sssnic_ethdev_tx_info {\n+\t/* offload enable flag */\n+\tuint16_t offload_en;\n+\t/*l4 payload offset*/\n+\tuint16_t payload_off;\n+\t/* number of txq entries */\n+\tuint16_t nb_entries;\n+\t/* number of tx segs */\n+\tuint16_t nb_segs;\n+};\n+\n #define SSSNIC_ETHDEV_TXQ_ENTRY_SZ_BITS 4\n #define SSSNIC_ETHDEV_TXQ_ENTRY_SZ (RTE_BIT32(SSSNIC_ETHDEV_TXQ_ENTRY_SZ_BITS))\n \n@@ -182,12 +193,44 @@ enum sssnic_ethdev_txq_entry_type {\n #define SSSNIC_ETHDEV_TX_CI_DEF_COALESCING_TIME 16\n #define SSSNIC_ETHDEV_TX_CI_DEF_PENDING_TIME 4\n \n+#define SSSNIC_ETHDEV_TX_CSUM_OFFLOAD_MASK                                     \\\n+\t(RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_TCP_CKSUM |                    \\\n+\t\tRTE_MBUF_F_TX_UDP_CKSUM | RTE_MBUF_F_TX_SCTP_CKSUM |           \\\n+\t\tRTE_MBUF_F_TX_OUTER_IP_CKSUM | RTE_MBUF_F_TX_TCP_SEG)\n+\n+#define SSSNIC_ETHDEV_TX_OFFLOAD_MASK                                          \\\n+\t(RTE_MBUF_F_TX_VLAN | SSSNIC_ETHDEV_TX_CSUM_OFFLOAD_MASK)\n+\n+#define SSSNIC_ETHDEV_TX_MAX_NUM_SEGS 38\n+#define SSSNIC_ETHDEV_TX_MAX_SEG_SIZE 65535\n+#define SSSNIC_ETHDEV_TX_MAX_PAYLOAD_OFF 221\n+#define SSSNIC_ETHDEV_TX_DEF_MSS 0x3e00\n+#define SSSNIC_ETHDEV_TX_MIN_MSS 0x50\n+#define SSSNIC_ETHDEV_TX_COMPACT_SEG_MAX_SIZE 0x3fff\n+\n+#define SSSNIC_ETHDEV_TXQ_DESC_ENTRY(txq, idx)                                 \\\n+\t(SSSNIC_WORKQ_ENTRY_CAST((txq)->workq, idx,                            \\\n+\t\tstruct sssnic_ethdev_tx_desc))\n+\n+#define SSSNIC_ETHDEV_TXQ_OFFLOAD_ENTRY(txq, idx)                              \\\n+\tSSSNIC_WORKQ_ENTRY_CAST((txq)->workq, idx,                             \\\n+\t\tstruct sssnic_ethdev_tx_offload)\n+\n+#define SSSNIC_ETHDEV_TXQ_SEG_ENTRY(txq, idx)                                  \\\n+\tSSSNIC_WORKQ_ENTRY_CAST((txq)->workq, idx, struct sssnic_ethdev_tx_seg)\n+\n static inline uint16_t\n sssnic_ethdev_txq_num_used_entries(struct sssnic_ethdev_txq *txq)\n {\n \treturn sssnic_workq_num_used_entries(txq->workq);\n }\n \n+static inline uint16_t\n+sssnic_ethdev_txq_num_idle_entries(struct sssnic_ethdev_txq *txq)\n+{\n+\treturn sssnic_workq_num_idle_entries(txq->workq);\n+}\n+\n static inline uint16_t\n sssnic_ethdev_txq_ci_get(struct sssnic_ethdev_txq *txq)\n {\n@@ -212,6 +255,12 @@ sssnic_ethdev_txq_consume(struct sssnic_ethdev_txq *txq, uint16_t num_entries)\n \tsssnic_workq_consume_fast(txq->workq, num_entries);\n }\n \n+static inline void\n+sssnic_ethdev_txq_produce(struct sssnic_ethdev_txq *txq, uint16_t num_entries)\n+{\n+\tsssnic_workq_produce_fast(txq->workq, num_entries);\n+}\n+\n int\n sssnic_ethdev_tx_queue_setup(struct rte_eth_dev *ethdev, uint16_t tx_queue_id,\n \tuint16_t nb_tx_desc, unsigned int socket_id,\n@@ -706,3 +755,358 @@ sssnic_ethdev_tx_queue_stats_clear(struct rte_eth_dev *ethdev, uint16_t qid)\n \t\t\t*(stat++) = 0;\n \t}\n }\n+\n+static inline uint16_t\n+sssnic_ethdev_tx_payload_calc(struct rte_mbuf *tx_mbuf)\n+{\n+\tif ((tx_mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) != 0) {\n+\t\tuint64_t mask = RTE_MBUF_F_TX_OUTER_IPV6 |\n+\t\t\t\tRTE_MBUF_F_TX_OUTER_IP_CKSUM |\n+\t\t\t\tRTE_MBUF_F_TX_TCP_SEG;\n+\n+\t\tif ((tx_mbuf->ol_flags & mask) != 0)\n+\t\t\treturn tx_mbuf->outer_l2_len + tx_mbuf->outer_l3_len +\n+\t\t\t       tx_mbuf->l2_len + tx_mbuf->l3_len +\n+\t\t\t       tx_mbuf->l4_len;\n+\t}\n+\n+\treturn tx_mbuf->l2_len + tx_mbuf->l3_len + tx_mbuf->l4_len;\n+}\n+\n+static inline int\n+sssnic_ethdev_tx_offload_check(struct rte_mbuf *tx_mbuf,\n+\tstruct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tuint64_t ol_flags = tx_mbuf->ol_flags;\n+\n+\tif ((ol_flags & SSSNIC_ETHDEV_TX_OFFLOAD_MASK) == 0) {\n+\t\ttx_info->offload_en = 0;\n+\t\treturn 0;\n+\t}\n+\n+#ifdef RTE_LIBRTE_ETHDEV_DEBUG\n+\tif (rte_validate_tx_offload(tx_mbuf) != 0) {\n+\t\tSSSNIC_TX_LOG(ERR, \"Bad tx mbuf offload flags: %\" PRIx64, ol_flags);\n+\t\treturn -EINVAL;\n+\t}\n+#endif\n+\n+\ttx_info->offload_en = 1;\n+\n+\tif (unlikely(((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) != 0) &&\n+\t\t     ((ol_flags & RTE_MBUF_F_TX_TUNNEL_VXLAN) == 0))) {\n+\t\tSSSNIC_TX_LOG(ERR, \"Only support VXLAN offload\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (unlikely((ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0)) {\n+\t\tuint16_t off = sssnic_ethdev_tx_payload_calc(tx_mbuf);\n+\t\tif (unlikely((off >> 1) > SSSNIC_ETHDEV_TX_MAX_PAYLOAD_OFF)) {\n+\t\t\tSSSNIC_TX_LOG(ERR, \"Bad tx payload offset: %u\", off);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\ttx_info->payload_off = off;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+sssnic_ethdev_tx_num_segs_calc(struct rte_mbuf *tx_mbuf,\n+\tstruct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tuint16_t nb_segs = tx_mbuf->nb_segs;\n+\n+\tif (tx_info->offload_en == 0) {\n+\t\t/* offload not enabled, need no offload entry,\n+\t\t * then txq entries equals tx_segs\n+\t\t */\n+\t\ttx_info->nb_entries = nb_segs;\n+\t} else {\n+\t\tif (unlikely(nb_segs > SSSNIC_ETHDEV_TX_MAX_NUM_SEGS)) {\n+\t\t\tSSSNIC_TX_LOG(ERR, \"Too many segment for tso\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/*offload enabled, need offload entry,\n+\t\t * then txq entries equals tx_segs + 1\n+\t\t */\n+\t\ttx_info->nb_entries = nb_segs + 1;\n+\t}\n+\n+\ttx_info->nb_segs = nb_segs;\n+\t;\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+sssnic_ethdev_tx_info_init(struct sssnic_ethdev_txq *txq,\n+\tstruct rte_mbuf *tx_mbuf, struct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tint ret;\n+\n+\t/* check tx offload valid and enabled */\n+\tret = sssnic_ethdev_tx_offload_check(tx_mbuf, tx_info);\n+\tif (unlikely(ret != 0)) {\n+\t\ttxq->stats.offload_errors++;\n+\t\treturn ret;\n+\t}\n+\n+\t/* Calculate how many num tx segs and num of txq entries are required*/\n+\tret = sssnic_ethdev_tx_num_segs_calc(tx_mbuf, tx_info);\n+\tif (unlikely(ret != 0)) {\n+\t\ttxq->stats.too_many_segs++;\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline void\n+sssnic_ethdev_tx_offload_setup(struct sssnic_ethdev_txq *txq,\n+\tstruct sssnic_ethdev_tx_desc *tx_desc, uint16_t pi,\n+\tstruct rte_mbuf *tx_mbuf, struct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tstruct sssnic_ethdev_tx_offload *offload;\n+\n+\t/* reset offload settings */\n+\toffload = SSSNIC_ETHDEV_TXQ_OFFLOAD_ENTRY(txq, pi);\n+\toffload->dw0 = 0;\n+\toffload->dw1 = 0;\n+\toffload->dw2 = 0;\n+\toffload->dw3 = 0;\n+\n+\tif (unlikely((tx_mbuf->ol_flags & RTE_MBUF_F_TX_VLAN) != 0)) {\n+\t\toffload->vlan_en = 1;\n+\t\toffload->vlan_tag = tx_mbuf->vlan_tci;\n+\t}\n+\n+\tif ((tx_mbuf->ol_flags & SSSNIC_ETHDEV_TX_CSUM_OFFLOAD_MASK) == 0)\n+\t\treturn;\n+\n+\tif ((tx_mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0) {\n+\t\toffload->inner_l3_csum_en = 1;\n+\t\toffload->inner_l4_csum_en = 1;\n+\n+\t\ttx_desc->tso_en = 1;\n+\t\ttx_desc->payload_off = tx_info->payload_off >> 1;\n+\t\ttx_desc->mss = tx_mbuf->tso_segsz;\n+\t} else {\n+\t\tif ((tx_mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) != 0)\n+\t\t\toffload->inner_l3_csum_en = 1;\n+\n+\t\tif ((tx_mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) != 0)\n+\t\t\toffload->inner_l4_csum_en = 1;\n+\t}\n+\n+\tif (tx_mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_VXLAN)\n+\t\toffload->tunnel_flag = 1;\n+\n+\tif (tx_mbuf->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM)\n+\t\toffload->l3_csum_en = 1;\n+}\n+\n+static inline int\n+sssnic_ethdev_tx_segs_setup(struct sssnic_ethdev_txq *txq,\n+\tstruct sssnic_ethdev_tx_desc *tx_desc, uint16_t pi,\n+\tstruct rte_mbuf *tx_mbuf, struct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tstruct sssnic_ethdev_tx_seg *tx_seg;\n+\tuint16_t idx_mask = txq->idx_mask;\n+\tuint16_t nb_segs, i;\n+\trte_iova_t seg_iova;\n+\n+\tnb_segs = tx_info->nb_segs;\n+\n+\t/* first segment info fill into tx desc entry*/\n+\tseg_iova = rte_mbuf_data_iova(tx_mbuf);\n+\ttx_desc->data_addr_hi = SSSNIC_UPPER_32_BITS(seg_iova);\n+\ttx_desc->data_addr_lo = SSSNIC_LOWER_32_BITS(seg_iova);\n+\ttx_desc->data_len = tx_mbuf->data_len;\n+\n+\t/* next tx segment */\n+\ttx_mbuf = tx_mbuf->next;\n+\n+\tfor (i = 1; i < nb_segs; i++) {\n+\t\tif (unlikely(tx_mbuf == NULL)) {\n+\t\t\ttxq->stats.null_segs++;\n+\t\t\tSSSNIC_TX_LOG(DEBUG, \"Tx mbuf segment is NULL\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (unlikely(tx_mbuf->data_len == 0)) {\n+\t\t\ttxq->stats.zero_len_segs++;\n+\t\t\tSSSNIC_TX_LOG(DEBUG,\n+\t\t\t\t\"Length of tx mbuf segment is zero\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tseg_iova = rte_mbuf_data_iova(tx_mbuf);\n+\t\ttx_seg = SSSNIC_ETHDEV_TXQ_SEG_ENTRY(txq, pi);\n+\t\ttx_seg->buf_hi_addr = SSSNIC_UPPER_32_BITS(seg_iova);\n+\t\ttx_seg->buf_lo_addr = SSSNIC_LOWER_32_BITS(seg_iova);\n+\t\ttx_seg->len = tx_mbuf->data_len;\n+\t\ttx_seg->resvd = 0;\n+\n+\t\tpi = (pi + 1) & idx_mask;\n+\t\ttx_mbuf = tx_mbuf->next;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+sssnic_ethdev_txq_entries_setup(struct sssnic_ethdev_txq *txq, uint16_t pi,\n+\tstruct rte_mbuf *tx_mbuf, struct sssnic_ethdev_tx_info *tx_info)\n+{\n+\tstruct sssnic_ethdev_tx_desc *tx_desc;\n+\tuint16_t idx_mask = txq->idx_mask;\n+\n+\t/* reset tx desc entry*/\n+\ttx_desc = SSSNIC_ETHDEV_TXQ_DESC_ENTRY(txq, pi);\n+\ttx_desc->dw0 = 0;\n+\ttx_desc->dw1 = 0;\n+\ttx_desc->dw2 = 0;\n+\ttx_desc->dw3 = 0;\n+\ttx_desc->owner = txq->owner;\n+\ttx_desc->uc = 1;\n+\n+\tif (tx_info->offload_en != 0) {\n+\t\t/* next_pi points to tx offload entry */\n+\t\tpi = (pi + 1) & idx_mask;\n+\t\tsssnic_ethdev_tx_offload_setup(txq, tx_desc, pi, tx_mbuf,\n+\t\t\ttx_info);\n+\n+\t\ttx_desc->entry_type = SSSNIC_ETHDEV_TXQ_ENTRY_EXTEND;\n+\t\ttx_desc->offload_en = 1;\n+\t\ttx_desc->num_segs = tx_info->nb_segs;\n+\n+\t\tif (tx_desc->mss == 0)\n+\t\t\ttx_desc->mss = SSSNIC_ETHDEV_TX_DEF_MSS;\n+\t\telse if (tx_desc->mss < SSSNIC_ETHDEV_TX_MIN_MSS)\n+\t\t\ttx_desc->mss = SSSNIC_ETHDEV_TX_MIN_MSS;\n+\n+\t} else {\n+\t\t/*\n+\t\t * if offload disabled and nb_tx_seg > 0 use extend tx entry\n+\t\t * else use default compact entry\n+\t\t */\n+\t\tif (tx_info->nb_segs > 1) {\n+\t\t\ttx_desc->num_segs = tx_info->nb_segs;\n+\t\t\ttx_desc->entry_type = SSSNIC_ETHDEV_TXQ_ENTRY_EXTEND;\n+\t\t} else {\n+\t\t\tif (unlikely(tx_mbuf->data_len >\n+\t\t\t\t     SSSNIC_ETHDEV_TX_COMPACT_SEG_MAX_SIZE)) {\n+\t\t\t\ttxq->stats.too_large_pkts++;\n+\t\t\t\tSSSNIC_TX_LOG(ERR,\n+\t\t\t\t\t\"Too large pakcet (size=%u) for compact tx entry\",\n+\t\t\t\t\ttx_mbuf->data_len);\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* get next_pi that points to tx seg entry */\n+\tpi = (pi + 1) & idx_mask;\n+\n+\treturn sssnic_ethdev_tx_segs_setup(txq, tx_desc, pi, tx_mbuf, tx_info);\n+}\n+\n+static inline void\n+sssnic_ethdev_txq_doorbell_ring(struct sssnic_ethdev_txq *txq, uint16_t pi)\n+{\n+\tuint64_t *db_addr;\n+\tstruct sssnic_ethdev_txq_doorbell db;\n+\tstatic const struct sssnic_ethdev_txq_doorbell default_db = {\n+\t\t.cf = 0,\n+\t\t.service = 1,\n+\t};\n+\n+\tdb.u64 = default_db.u64;\n+\tdb.qid = txq->qid;\n+\tdb.cos = txq->cos;\n+\tdb.pi_hi = (pi >> 8) & 0xff;\n+\n+\tdb_addr = ((uint64_t *)txq->doorbell) + (pi & 0xff);\n+\n+\trte_write64(db.u64, db_addr);\n+}\n+\n+uint16_t\n+sssnic_ethdev_tx_pkt_burst(void *tx_queue, struct rte_mbuf **tx_pkts,\n+\tuint16_t nb_pkts)\n+{\n+\tstruct sssnic_ethdev_txq *txq = (struct sssnic_ethdev_txq *)tx_queue;\n+\tstruct sssnic_ethdev_tx_entry *txe;\n+\tstruct rte_mbuf *txm;\n+\tstruct sssnic_ethdev_tx_info tx_info;\n+\tuint64_t tx_bytes = 0;\n+\tuint16_t nb_tx = 0;\n+\tuint16_t idle_entries;\n+\tuint16_t pi;\n+\tint ret;\n+\n+\t/* cleanup previous xmit if idle entries is less than tx_free_thresh*/\n+\tidle_entries = sssnic_ethdev_txq_num_idle_entries(txq) - 1;\n+\tif (unlikely(idle_entries < txq->tx_free_thresh))\n+\t\tsssnic_ethdev_txq_pktmbufs_cleanup(txq);\n+\n+\tpi = sssnic_ethdev_txq_pi_get(txq);\n+\n+\twhile (nb_tx < nb_pkts) {\n+\t\ttxm = tx_pkts[nb_tx];\n+\n+\t\tret = sssnic_ethdev_tx_info_init(txq, txm, &tx_info);\n+\t\tif (unlikely(ret != 0))\n+\t\t\tbreak;\n+\n+\t\tidle_entries = sssnic_ethdev_txq_num_idle_entries(txq) - 1;\n+\n+\t\t/* check if there are enough txq entries to xmit one packet */\n+\t\tif (unlikely(idle_entries < tx_info.nb_entries)) {\n+\t\t\tsssnic_ethdev_txq_pktmbufs_cleanup(txq);\n+\t\t\tidle_entries =\n+\t\t\t\tsssnic_ethdev_txq_num_idle_entries(txq) - 1;\n+\t\t\tif (idle_entries < tx_info.nb_entries) {\n+\t\t\t\tSSSNIC_TX_LOG(ERR,\n+\t\t\t\t\t\"No tx entries, idle_entries: %u, expect %u\",\n+\t\t\t\t\tidle_entries, tx_info.nb_entries);\n+\t\t\t\ttxq->stats.nobuf++;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* setup txq entries, include tx_desc, offload, seg */\n+\t\tret = sssnic_ethdev_txq_entries_setup(txq, pi, txm, &tx_info);\n+\t\tif (unlikely(ret != 0))\n+\t\t\tbreak;\n+\n+\t\ttxe = &txq->txe[pi];\n+\t\ttxe->pktmbuf = txm;\n+\t\ttxe->num_workq_entries = tx_info.nb_entries;\n+\n+\t\tif (unlikely((pi + tx_info.nb_entries) >= txq->depth))\n+\t\t\ttxq->owner = !txq->owner;\n+\n+\t\tsssnic_ethdev_txq_produce(txq, tx_info.nb_entries);\n+\n+\t\tpi = sssnic_ethdev_txq_pi_get(txq);\n+\t\tnb_tx++;\n+\t\ttx_bytes += txm->pkt_len;\n+\n+\t\tSSSNIC_TX_LOG(DEBUG,\n+\t\t\t\"Transmitted one packet on port %u, len=%u, nb_seg=%u, tso_segsz=%u, ol_flags=%\"\n+\t\t\tPRIx64, txq->port, txm->pkt_len, txm->nb_segs, txm->tso_segsz,\n+\t\t\ttxm->ol_flags);\n+\t}\n+\n+\tif (likely(nb_tx > 0)) {\n+\t\tsssnic_ethdev_txq_doorbell_ring(txq, pi);\n+\t\ttxq->stats.packets += nb_tx;\n+\t\ttxq->stats.bytes += tx_bytes;\n+\t\ttxq->stats.burst = nb_tx;\n+\t}\n+\n+\treturn nb_tx;\n+}\ndiff --git a/drivers/net/sssnic/sssnic_ethdev_tx.h b/drivers/net/sssnic/sssnic_ethdev_tx.h\nindex f04c3d5be8..3a7cd47080 100644\n--- a/drivers/net/sssnic/sssnic_ethdev_tx.h\n+++ b/drivers/net/sssnic/sssnic_ethdev_tx.h\n@@ -37,5 +37,7 @@ int sssnic_ethdev_tx_queue_stats_get(struct rte_eth_dev *ethdev, uint16_t qid,\n \tstruct sssnic_ethdev_txq_stats *stats);\n void sssnic_ethdev_tx_queue_stats_clear(struct rte_eth_dev *ethdev,\n \tuint16_t qid);\n+uint16_t sssnic_ethdev_tx_pkt_burst(void *tx_queue, struct rte_mbuf **tx_pkts,\n+\tuint16_t nb_pkts);\n \n #endif /* _SSSNIC_ETHDEV_TX_H_ */\n",
    "prefixes": [
        "v4",
        "24/32"
    ]
}