get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 76656,
    "url": "http://patches.dpdk.org/api/patches/76656/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200907090825.1761-5-huwei013@chinasoftinc.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20200907090825.1761-5-huwei013@chinasoftinc.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200907090825.1761-5-huwei013@chinasoftinc.com",
    "date": "2020-09-07T09:08:21",
    "name": "[4/8] net/hns3: add simple Tx process function",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "dcf35849b437d17a60baed2fdd632a38cecda9ee",
    "submitter": {
        "id": 1537,
        "url": "http://patches.dpdk.org/api/people/1537/?format=api",
        "name": "Wei Hu (Xavier)",
        "email": "huwei013@chinasoftinc.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200907090825.1761-5-huwei013@chinasoftinc.com/mbox/",
    "series": [
        {
            "id": 11986,
            "url": "http://patches.dpdk.org/api/series/11986/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11986",
            "date": "2020-09-07T09:08:17",
            "name": "net/hns3: updates for Rx Tx",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/11986/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/76656/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/76656/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D7C62A04B9;\n\tMon,  7 Sep 2020 11:09:40 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 4ED121C115;\n\tMon,  7 Sep 2020 11:09:15 +0200 (CEST)",
            "from mail.chinasoftinc.com (unknown [114.113.233.8])\n by dpdk.org (Postfix) with ESMTP id 8CFD21C10F\n for <dev@dpdk.org>; Mon,  7 Sep 2020 11:09:12 +0200 (CEST)",
            "from localhost.localdomain (65.49.108.226) by INCCAS002.ito.icss\n (10.168.0.60) with Microsoft SMTP Server id 14.3.487.0; Mon, 7 Sep 2020\n 17:09:08 +0800"
        ],
        "From": "\"Wei Hu (Xavier)\" <huwei013@chinasoftinc.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<xavier.huwei@huawei.com>",
        "Date": "Mon, 7 Sep 2020 17:08:21 +0800",
        "Message-ID": "<20200907090825.1761-5-huwei013@chinasoftinc.com>",
        "X-Mailer": "git-send-email 2.9.5",
        "In-Reply-To": "<20200907090825.1761-1-huwei013@chinasoftinc.com>",
        "References": "<20200907090825.1761-1-huwei013@chinasoftinc.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[65.49.108.226]",
        "Subject": "[dpdk-dev] [PATCH 4/8] net/hns3: add simple Tx process function",
        "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 <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",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: \"Wei Hu (Xavier)\" <xavier.huwei@huawei.com>\n\nThis patch adds simple Tx process function. When multiple segment packets\nare not needed, Which means that DEV_TX_OFFLOAD_MBUF_FAST_FREE offload is\nnot set, we can simple Tx process.\n\nSigned-off-by: Huisong Li <lihuisong@huawei.com>\nSigned-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>\nSigned-off-by: Chengwen Feng <fengchengwen@huawei.com>\n---\n drivers/net/hns3/hns3_ethdev.c    |   6 +\n drivers/net/hns3/hns3_ethdev.h    |   1 +\n drivers/net/hns3/hns3_ethdev_vf.c |   6 +\n drivers/net/hns3/hns3_rxtx.c      | 260 +++++++++++++++++++++++++++++++++++---\n drivers/net/hns3/hns3_rxtx.h      |  34 +++++\n 5 files changed, 292 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c\nindex 5d612f1..8701994 100644\n--- a/drivers/net/hns3/hns3_ethdev.c\n+++ b/drivers/net/hns3/hns3_ethdev.c\n@@ -2352,6 +2352,7 @@ hns3_dev_configure(struct rte_eth_dev *dev)\n \t\tgoto cfg_err;\n \n \thns->rx_simple_allowed = true;\n+\thns->tx_simple_allowed = true;\n \thns3_init_rx_ptype_tble(dev);\n \thw->adapter_state = HNS3_NIC_CONFIGURED;\n \n@@ -2512,6 +2513,10 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)\n \t\t.rx_drop_en = 1,\n \t\t.offloads = 0,\n \t};\n+\tinfo->default_txconf = (struct rte_eth_txconf) {\n+\t\t.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,\n+\t\t.offloads = 0,\n+\t};\n \n \tinfo->vmdq_queue_num = 0;\n \n@@ -5545,6 +5550,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {\n \t.rxq_info_get           = hns3_rxq_info_get,\n \t.txq_info_get           = hns3_txq_info_get,\n \t.rx_burst_mode_get      = hns3_rx_burst_mode_get,\n+\t.tx_burst_mode_get      = hns3_tx_burst_mode_get,\n \t.flow_ctrl_get          = hns3_flow_ctrl_get,\n \t.flow_ctrl_set          = hns3_flow_ctrl_set,\n \t.priority_flow_ctrl_set = hns3_priority_flow_ctrl_set,\ndiff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h\nindex d93c5b2..ef85034 100644\n--- a/drivers/net/hns3/hns3_ethdev.h\n+++ b/drivers/net/hns3/hns3_ethdev.h\n@@ -643,6 +643,7 @@ struct hns3_adapter {\n \t};\n \n \tbool rx_simple_allowed;\n+\tbool tx_simple_allowed;\n \tstruct hns3_ptype_table ptype_tbl __rte_cache_min_aligned;\n };\n \ndiff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c\nindex 0f155d8..915b896 100644\n--- a/drivers/net/hns3/hns3_ethdev_vf.c\n+++ b/drivers/net/hns3/hns3_ethdev_vf.c\n@@ -822,6 +822,7 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)\n \t\tgoto cfg_err;\n \n \thns->rx_simple_allowed = true;\n+\thns->tx_simple_allowed = true;\n \thns3_init_rx_ptype_tble(dev);\n \n \thw->adapter_state = HNS3_NIC_CONFIGURED;\n@@ -957,6 +958,10 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)\n \t\t.rx_drop_en = 1,\n \t\t.offloads = 0,\n \t};\n+\tinfo->default_txconf = (struct rte_eth_txconf) {\n+\t\t.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,\n+\t\t.offloads = 0,\n+\t};\n \n \tinfo->vmdq_queue_num = 0;\n \n@@ -2541,6 +2546,7 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {\n \t.rxq_info_get       = hns3_rxq_info_get,\n \t.txq_info_get       = hns3_txq_info_get,\n \t.rx_burst_mode_get  = hns3_rx_burst_mode_get,\n+\t.tx_burst_mode_get  = hns3_tx_burst_mode_get,\n \t.mac_addr_add       = hns3vf_add_mac_addr,\n \t.mac_addr_remove    = hns3vf_remove_mac_addr,\n \t.mac_addr_set       = hns3vf_set_default_mac_addr,\ndiff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c\nindex 38ad454..08a3dcd 100644\n--- a/drivers/net/hns3/hns3_rxtx.c\n+++ b/drivers/net/hns3/hns3_rxtx.c\n@@ -1952,27 +1952,72 @@ hns3_get_rx_function(struct rte_eth_dev *dev)\n \n \treturn hns3_recv_scattered_pkts;\n }\n+\n+static int\n+hns3_tx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_txconf *conf,\n+\t\t\t uint16_t nb_desc, uint16_t *tx_rs_thresh,\n+\t\t\t uint16_t *tx_free_thresh, uint16_t idx)\n+{\n+#define HNS3_TX_RS_FREE_THRESH_GAP\t8\n+\tuint16_t rs_thresh, free_thresh, fast_free_thresh;\n+\n+\tif (nb_desc > HNS3_MAX_RING_DESC || nb_desc < HNS3_MIN_RING_DESC ||\n+\t    nb_desc % HNS3_ALIGN_RING_DESC) {\n+\t\thns3_err(hw, \"number (%u) of tx descriptors is invalid\",\n+\t\t\t nb_desc);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trs_thresh = (conf->tx_rs_thresh > 0) ?\n+\t\t\tconf->tx_rs_thresh : HNS3_DEFAULT_TX_RS_THRESH;\n+\tfree_thresh = (conf->tx_free_thresh > 0) ?\n+\t\t\tconf->tx_free_thresh : HNS3_DEFAULT_TX_FREE_THRESH;\n+\tif (rs_thresh + free_thresh > nb_desc || nb_desc % rs_thresh ||\n+\t    rs_thresh >= nb_desc - HNS3_TX_RS_FREE_THRESH_GAP ||\n+\t    free_thresh >= nb_desc - HNS3_TX_RS_FREE_THRESH_GAP) {\n+\t\thns3_err(hw, \"tx_rs_thresh (%d) tx_free_thresh (%d) nb_desc \"\n+\t\t\t \"(%d) of tx descriptors for port=%d queue=%d check \"\n+\t\t\t \"fail!\",\n+\t\t\t rs_thresh, free_thresh, nb_desc, hw->data->port_id,\n+\t\t\t idx);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (conf->tx_free_thresh == 0) {\n+\t\t/* Fast free Tx memory buffer to improve cache hit rate */\n+\t\tfast_free_thresh = nb_desc - rs_thresh;\n+\t\tif (fast_free_thresh >=\n+\t\t    HNS3_TX_FAST_FREE_AHEAD + HNS3_DEFAULT_TX_FREE_THRESH)\n+\t\t\tfree_thresh = fast_free_thresh -\n+\t\t\t\t\tHNS3_TX_FAST_FREE_AHEAD;\n+\t}\n+\n+\t*tx_rs_thresh = rs_thresh;\n+\t*tx_free_thresh = free_thresh;\n+\treturn 0;\n+}\n+\n int\n hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,\n \t\t    unsigned int socket_id, const struct rte_eth_txconf *conf)\n {\n \tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tuint16_t tx_rs_thresh, tx_free_thresh;\n \tstruct hns3_hw *hw = &hns->hw;\n \tstruct hns3_queue_info q_info;\n \tstruct hns3_tx_queue *txq;\n \tint tx_entry_len;\n+\tint ret;\n \n \tif (dev->data->dev_started) {\n \t\thns3_err(hw, \"tx_queue_setup after dev_start no supported\");\n \t\treturn -EINVAL;\n \t}\n \n-\tif (nb_desc > HNS3_MAX_RING_DESC || nb_desc < HNS3_MIN_RING_DESC ||\n-\t    nb_desc % HNS3_ALIGN_RING_DESC) {\n-\t\thns3_err(hw, \"Number (%u) of tx descriptors is invalid\",\n-\t\t\t    nb_desc);\n-\t\treturn -EINVAL;\n-\t}\n+\tret = hns3_tx_queue_conf_check(hw, conf, nb_desc,\n+\t\t\t\t       &tx_rs_thresh, &tx_free_thresh, idx);\n+\tif (ret)\n+\t\treturn ret;\n \n \tif (dev->data->tx_queues[idx] != NULL) {\n \t\thns3_tx_queue_release(dev->data->tx_queues[idx]);\n@@ -2005,11 +2050,15 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,\n \ttxq->next_to_use = 0;\n \ttxq->next_to_clean = 0;\n \ttxq->tx_bd_ready = txq->nb_tx_desc - 1;\n+\ttxq->tx_free_thresh = tx_free_thresh;\n+\ttxq->tx_rs_thresh = tx_rs_thresh;\n \ttxq->port_id = dev->data->port_id;\n \ttxq->pvid_state = hw->port_base_vlan_cfg.state;\n \ttxq->configured = true;\n \ttxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +\n \t\t\t\tidx * HNS3_TQP_REG_SIZE);\n+\ttxq->io_tail_reg = (volatile void *)((char *)txq->io_base +\n+\t\t\t\t\t     HNS3_RING_TX_TAIL_REG);\n \ttxq->min_tx_pkt_len = hw->min_tx_pkt_len;\n \ttxq->over_length_pkt_cnt = 0;\n \ttxq->exceed_limit_bd_pkt_cnt = 0;\n@@ -2024,12 +2073,6 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,\n \treturn 0;\n }\n \n-static inline void\n-hns3_queue_xmit(struct hns3_tx_queue *txq, uint32_t buf_num)\n-{\n-\thns3_write_dev(txq, HNS3_RING_TX_TAIL_REG, buf_num);\n-}\n-\n static void\n hns3_tx_free_useless_buffer(struct hns3_tx_queue *txq)\n {\n@@ -2798,6 +2841,154 @@ hns3_check_non_tso_pkt(uint16_t nb_buf, struct rte_mbuf **m_seg,\n \treturn 0;\n }\n \n+static inline void\n+hns3_tx_free_buffer_simple(struct hns3_tx_queue *txq)\n+{\n+\tstruct hns3_entry *tx_entry;\n+\tstruct hns3_desc *desc;\n+\tuint16_t tx_next_clean;\n+\tint i;\n+\n+\twhile (1) {\n+\t\tif (HNS3_GET_TX_QUEUE_PEND_BD_NUM(txq) < txq->tx_rs_thresh)\n+\t\t\tbreak;\n+\n+\t\t/*\n+\t\t * All mbufs can be released only when the VLD bits of all\n+\t\t * descriptors in a batch are cleared.\n+\t\t */\n+\t\ttx_next_clean = (txq->next_to_clean + txq->tx_rs_thresh - 1) %\n+\t\t\t\ttxq->nb_tx_desc;\n+\t\tdesc = &txq->tx_ring[tx_next_clean];\n+\t\tfor (i = 0; i < txq->tx_rs_thresh; i++) {\n+\t\t\tif (rte_le_to_cpu_16(desc->tx.tp_fe_sc_vld_ra_ri) &\n+\t\t\t\t\tBIT(HNS3_TXD_VLD_B))\n+\t\t\t\treturn;\n+\t\t\tdesc--;\n+\t\t}\n+\n+\t\ttx_entry = &txq->sw_ring[txq->next_to_clean];\n+\n+\t\tfor (i = 0; i < txq->tx_rs_thresh; i++)\n+\t\t\trte_prefetch0((tx_entry + i)->mbuf);\n+\t\tfor (i = 0; i < txq->tx_rs_thresh; i++, tx_entry++) {\n+\t\t\trte_mempool_put(tx_entry->mbuf->pool, tx_entry->mbuf);\n+\t\t\ttx_entry->mbuf = NULL;\n+\t\t}\n+\n+\t\ttxq->next_to_clean = (tx_next_clean + 1) % txq->nb_tx_desc;\n+\t\ttxq->tx_bd_ready += txq->tx_rs_thresh;\n+\t}\n+}\n+\n+static inline void\n+hns3_tx_backup_1mbuf(struct hns3_entry *tx_entry, struct rte_mbuf **pkts)\n+{\n+\ttx_entry->mbuf = pkts[0];\n+}\n+\n+static inline void\n+hns3_tx_backup_4mbuf(struct hns3_entry *tx_entry, struct rte_mbuf **pkts)\n+{\n+\thns3_tx_backup_1mbuf(&tx_entry[0], &pkts[0]);\n+\thns3_tx_backup_1mbuf(&tx_entry[1], &pkts[1]);\n+\thns3_tx_backup_1mbuf(&tx_entry[2], &pkts[2]);\n+\thns3_tx_backup_1mbuf(&tx_entry[3], &pkts[3]);\n+}\n+\n+static inline void\n+hns3_tx_setup_4bd(struct hns3_desc *txdp, struct rte_mbuf **pkts)\n+{\n+#define PER_LOOP_NUM\t4\n+\tconst uint16_t bd_flag = BIT(HNS3_TXD_VLD_B) | BIT(HNS3_TXD_FE_B);\n+\tuint64_t dma_addr;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < PER_LOOP_NUM; i++, txdp++, pkts++) {\n+\t\tdma_addr = rte_mbuf_data_iova(*pkts);\n+\t\ttxdp->addr = rte_cpu_to_le_64(dma_addr);\n+\t\ttxdp->tx.send_size = rte_cpu_to_le_16((*pkts)->data_len);\n+\t\ttxdp->tx.paylen = 0;\n+\t\ttxdp->tx.type_cs_vlan_tso_len = 0;\n+\t\ttxdp->tx.ol_type_vlan_len_msec = 0;\n+\t\ttxdp->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(bd_flag);\n+\t}\n+}\n+\n+static inline void\n+hns3_tx_setup_1bd(struct hns3_desc *txdp, struct rte_mbuf **pkts)\n+{\n+\tconst uint16_t bd_flag = BIT(HNS3_TXD_VLD_B) | BIT(HNS3_TXD_FE_B);\n+\tuint64_t dma_addr;\n+\n+\tdma_addr = rte_mbuf_data_iova(*pkts);\n+\ttxdp->addr = rte_cpu_to_le_64(dma_addr);\n+\ttxdp->tx.send_size = rte_cpu_to_le_16((*pkts)->data_len);\n+\ttxdp->tx.paylen = 0;\n+\ttxdp->tx.type_cs_vlan_tso_len = 0;\n+\ttxdp->tx.ol_type_vlan_len_msec = 0;\n+\ttxdp->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(bd_flag);\n+}\n+\n+static inline void\n+hns3_tx_fill_hw_ring(struct hns3_tx_queue *txq,\n+\t\t     struct rte_mbuf **pkts,\n+\t\t     uint16_t nb_pkts)\n+{\n+#define PER_LOOP_NUM\t4\n+#define PER_LOOP_MASK\t(PER_LOOP_NUM - 1)\n+\tstruct hns3_desc *txdp = &txq->tx_ring[txq->next_to_use];\n+\tstruct hns3_entry *tx_entry = &txq->sw_ring[txq->next_to_use];\n+\tconst uint32_t mainpart = (nb_pkts & ((uint32_t)~PER_LOOP_MASK));\n+\tconst uint32_t leftover = (nb_pkts & ((uint32_t)PER_LOOP_MASK));\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < mainpart; i += PER_LOOP_NUM) {\n+\t\thns3_tx_backup_4mbuf(tx_entry + i, pkts + i);\n+\t\thns3_tx_setup_4bd(txdp + i, pkts + i);\n+\t}\n+\tif (unlikely(leftover > 0)) {\n+\t\tfor (i = 0; i < leftover; i++) {\n+\t\t\thns3_tx_backup_1mbuf(tx_entry + mainpart + i,\n+\t\t\t\t\t     pkts + mainpart + i);\n+\t\t\thns3_tx_setup_1bd(txdp + mainpart + i,\n+\t\t\t\t\t  pkts + mainpart + i);\n+\t\t}\n+\t}\n+}\n+\n+uint16_t\n+hns3_xmit_pkts_simple(void *tx_queue,\n+\t\t      struct rte_mbuf **tx_pkts,\n+\t\t      uint16_t nb_pkts)\n+{\n+\tstruct hns3_tx_queue *txq = tx_queue;\n+\tuint16_t nb_tx = 0;\n+\n+\thns3_tx_free_buffer_simple(txq);\n+\n+\tnb_pkts = RTE_MIN(txq->tx_bd_ready, nb_pkts);\n+\tif (unlikely(nb_pkts == 0)) {\n+\t\tif (txq->tx_bd_ready == 0)\n+\t\t\ttxq->queue_full_cnt++;\n+\t\treturn 0;\n+\t}\n+\n+\ttxq->tx_bd_ready -= nb_pkts;\n+\tif (txq->next_to_use + nb_pkts > txq->nb_tx_desc) {\n+\t\tnb_tx = txq->nb_tx_desc - txq->next_to_use;\n+\t\thns3_tx_fill_hw_ring(txq, tx_pkts, nb_tx);\n+\t\ttxq->next_to_use = 0;\n+\t}\n+\n+\thns3_tx_fill_hw_ring(txq, tx_pkts + nb_tx, nb_pkts - nb_tx);\n+\ttxq->next_to_use += nb_pkts - nb_tx;\n+\n+\thns3_write_reg_opt(txq->io_tail_reg, nb_pkts);\n+\n+\treturn nb_pkts;\n+}\n+\n uint16_t\n hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n {\n@@ -2909,11 +3100,47 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n end_of_tx:\n \n \tif (likely(nb_tx))\n-\t\thns3_queue_xmit(txq, nb_hold);\n+\t\thns3_write_reg_opt(txq->io_tail_reg, nb_hold);\n \n \treturn nb_tx;\n }\n \n+int\n+hns3_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,\n+\t\t       struct rte_eth_burst_mode *mode)\n+{\n+\teth_tx_burst_t pkt_burst = dev->tx_pkt_burst;\n+\tconst char *info = NULL;\n+\n+\tif (pkt_burst == hns3_xmit_pkts_simple)\n+\t\tinfo = \"Scalar Simple\";\n+\telse if (pkt_burst == hns3_xmit_pkts)\n+\t\tinfo = \"Scalar\";\n+\n+\tif (info == NULL)\n+\t\treturn -EINVAL;\n+\n+\tsnprintf(mode->info, sizeof(mode->info), \"%s\", info);\n+\n+\treturn 0;\n+}\n+\n+static eth_tx_burst_t\n+hns3_get_tx_function(struct rte_eth_dev *dev, eth_tx_prep_t *prep)\n+{\n+\tuint64_t offloads = dev->data->dev_conf.txmode.offloads;\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\n+\tif (hns->tx_simple_allowed &&\n+\t    offloads == (offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE)) {\n+\t\t*prep = NULL;\n+\t\treturn hns3_xmit_pkts_simple;\n+\t}\n+\n+\t*prep = hns3_prep_pkts;\n+\treturn hns3_xmit_pkts;\n+}\n+\n static uint16_t\n hns3_dummy_rxtx_burst(void *dpdk_txq __rte_unused,\n \t\t      struct rte_mbuf **pkts __rte_unused,\n@@ -2925,12 +3152,13 @@ hns3_dummy_rxtx_burst(void *dpdk_txq __rte_unused,\n void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev)\n {\n \tstruct hns3_adapter *hns = eth_dev->data->dev_private;\n+\teth_tx_prep_t prep = NULL;\n \n \tif (hns->hw.adapter_state == HNS3_NIC_STARTED &&\n \t    rte_atomic16_read(&hns->hw.reset.resetting) == 0) {\n \t\teth_dev->rx_pkt_burst = hns3_get_rx_function(eth_dev);\n-\t\teth_dev->tx_pkt_burst = hns3_xmit_pkts;\n-\t\teth_dev->tx_pkt_prepare = hns3_prep_pkts;\n+\t\teth_dev->tx_pkt_burst = hns3_get_tx_function(eth_dev, &prep);\n+\t\teth_dev->tx_pkt_prepare = prep;\n \t} else {\n \t\teth_dev->rx_pkt_burst = hns3_dummy_rxtx_burst;\n \t\teth_dev->tx_pkt_burst = hns3_dummy_rxtx_burst;\n@@ -2966,5 +3194,7 @@ hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,\n \n \tqinfo->nb_desc = txq->nb_tx_desc;\n \tqinfo->conf.offloads = dev->data->dev_conf.txmode.offloads;\n+\tqinfo->conf.tx_rs_thresh = txq->tx_rs_thresh;\n+\tqinfo->conf.tx_free_thresh = txq->tx_free_thresh;\n \tqinfo->conf.tx_deferred_start = txq->tx_deferred_start;\n }\ndiff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h\nindex 3d3f0a0..9933494 100644\n--- a/drivers/net/hns3/hns3_rxtx.h\n+++ b/drivers/net/hns3/hns3_rxtx.h\n@@ -13,6 +13,9 @@\n #define HNS3_BULK_ALLOC_MBUF_NUM\t32\n \n #define HNS3_DEFAULT_RX_FREE_THRESH\t32\n+#define HNS3_DEFAULT_TX_FREE_THRESH\t32\n+#define HNS3_DEFAULT_TX_RS_THRESH\t32\n+#define HNS3_TX_FAST_FREE_AHEAD\t\t64\n \n #define HNS3_512_BD_BUF_SIZE\t512\n #define HNS3_1K_BD_BUF_SIZE\t1024\n@@ -282,6 +285,7 @@ struct hns3_rx_queue {\n \n struct hns3_tx_queue {\n \tvoid *io_base;\n+\tvolatile void *io_tail_reg;\n \tstruct hns3_adapter *hns;\n \tstruct hns3_desc *tx_ring;\n \tuint64_t tx_ring_phys_addr; /* TX ring DMA address */\n@@ -291,10 +295,32 @@ struct hns3_tx_queue {\n \tuint16_t queue_id;\n \tuint16_t port_id;\n \tuint16_t nb_tx_desc;\n+\t/*\n+\t * index of next BD whose corresponding rte_mbuf can be released by\n+\t * driver.\n+\t */\n \tuint16_t next_to_clean;\n+\t/* index of next BD to be filled by driver to send packet */\n \tuint16_t next_to_use;\n+\t/* num of remaining BDs ready to be filled by driver to send packet */\n \tuint16_t tx_bd_ready;\n \n+\t/* threshold for free tx buffer if available BDs less than this value */\n+\tuint16_t tx_free_thresh;\n+\n+\t/*\n+\t * For better performance in tx datapath, releasing mbuf in batches is\n+\t * required.\n+\t * Only checking the VLD bit of the last descriptor in a batch of the\n+\t * thresh descriptors does not mean that these descriptors are all sent\n+\t * by hardware successfully. So we need to check that the VLD bits of\n+\t * all descriptors are cleared. and then free all mbufs in the batch.\n+\t * - tx_rs_thresh\n+\t *   Number of mbufs released at a time.\n+\n+\t */\n+\tuint16_t tx_rs_thresh;\n+\n \t/*\n \t * port based vlan configuration state.\n \t * value range: HNS3_PORT_BASE_VLAN_DISABLE / HNS3_PORT_BASE_VLAN_ENABLE\n@@ -360,6 +386,9 @@ struct hns3_tx_queue {\n \tuint64_t pkt_padding_fail_cnt;\n };\n \n+#define HNS3_GET_TX_QUEUE_PEND_BD_NUM(txq) \\\n+\t\t((txq)->nb_tx_desc - 1 - (txq)->tx_bd_ready)\n+\n struct hns3_queue_info {\n \tconst char *type;   /* point to queue memory name */\n \tconst char *ring_name;  /* point to hardware ring name */\n@@ -525,8 +554,13 @@ int hns3_rx_burst_mode_get(struct rte_eth_dev *dev,\n \t\t\t   struct rte_eth_burst_mode *mode);\n uint16_t hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,\n \t\t\tuint16_t nb_pkts);\n+uint16_t hns3_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,\n+\t\t\t       uint16_t nb_pkts);\n uint16_t hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,\n \t\t\tuint16_t nb_pkts);\n+int hns3_tx_burst_mode_get(struct rte_eth_dev *dev,\n+\t\t\t   __rte_unused uint16_t queue_id,\n+\t\t\t   struct rte_eth_burst_mode *mode);\n const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev);\n void hns3_init_rx_ptype_tble(struct rte_eth_dev *dev);\n void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev);\n",
    "prefixes": [
        "4/8"
    ]
}