support tx/rx queue setup and release add hw bd
queue reset,sw queue reset.

Signed-off-by: Wenbo Cao <caowe...@mucse.com>
---
 doc/guides/nics/rnp.rst             |   1 +
 drivers/net/rnp/base/meson.build    |   1 +
 drivers/net/rnp/base/rnp_bdq_if.c   | 397 ++++++++++++++++++++++++++++++
 drivers/net/rnp/base/rnp_bdq_if.h   | 149 +++++++++++
 drivers/net/rnp/base/rnp_common.h   |   4 +
 drivers/net/rnp/base/rnp_dma_regs.h |  45 ++++
 drivers/net/rnp/base/rnp_eth_regs.h |   4 +
 drivers/net/rnp/base/rnp_hw.h       |   3 +
 drivers/net/rnp/base/rnp_osdep.h    |  13 +
 drivers/net/rnp/meson.build         |   1 +
 drivers/net/rnp/rnp.h               |   2 +
 drivers/net/rnp/rnp_ethdev.c        |  29 +++
 drivers/net/rnp/rnp_rxtx.c          | 476 ++++++++++++++++++++++++++++++++++++
 drivers/net/rnp/rnp_rxtx.h          | 123 ++++++++++
 14 files changed, 1248 insertions(+)
 create mode 100644 drivers/net/rnp/base/rnp_bdq_if.c
 create mode 100644 drivers/net/rnp/base/rnp_bdq_if.h
 create mode 100644 drivers/net/rnp/rnp_rxtx.c
 create mode 100644 drivers/net/rnp/rnp_rxtx.h

diff --git a/doc/guides/nics/rnp.rst b/doc/guides/nics/rnp.rst
index 62585ac..5417593 100644
--- a/doc/guides/nics/rnp.rst
+++ b/doc/guides/nics/rnp.rst
@@ -10,6 +10,7 @@ driver support for the inbuilt network device found in the 
**Mucse RNP**
 Features
 --------
 
+- Multiple queues for TX and RX
 - Promiscuous mode
 
 Prerequisites
diff --git a/drivers/net/rnp/base/meson.build b/drivers/net/rnp/base/meson.build
index b9db033..c2ef0d0 100644
--- a/drivers/net/rnp/base/meson.build
+++ b/drivers/net/rnp/base/meson.build
@@ -7,6 +7,7 @@ sources = [
         'rnp_mbx_fw.c',
         'rnp_common.c',
         'rnp_mac.c',
+       'rnp_bdq_if.c',
 ]
 
 error_cflags = ['-Wno-unused-value',
diff --git a/drivers/net/rnp/base/rnp_bdq_if.c 
b/drivers/net/rnp/base/rnp_bdq_if.c
new file mode 100644
index 0000000..cc3fe51
--- /dev/null
+++ b/drivers/net/rnp/base/rnp_bdq_if.c
@@ -0,0 +1,397 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Mucse IC Design Ltd.
+ */
+
+#include "rnp_osdep.h"
+
+#include "../rnp.h"
+#include "rnp_dma_regs.h"
+#include "rnp_eth_regs.h"
+#include "rnp_bdq_if.h"
+#include "rnp_common.h"
+#include "../rnp_rxtx.h"
+
+static void
+rnp_read_mac_veb(struct rnp_hw *hw,
+                 u16 nr_lane,
+                 u16 vf_id,
+                 struct rnp_veb_cfg *cfg)
+{
+       cfg->mac_lo = RNP_E_REG_RD(hw, RNP_VEB_MAC_LO(nr_lane, vf_id));
+       cfg->mac_hi = RNP_E_REG_RD(hw, RNP_VEB_MAC_HI(nr_lane, vf_id));
+       cfg->ring = RNP_E_REG_RD(hw, RNP_VEB_VF_RING(nr_lane, vf_id));
+}
+
+static void
+rnp_update_mac_veb(struct rnp_hw *hw,
+                  u16 nr_lane,
+                  u16 vf_id,
+                  struct rnp_veb_cfg *cfg)
+{
+       u32 reg = cfg->ring;
+       u16 idx = 0;
+
+       idx = nr_lane;
+       wmb();
+       RNP_E_REG_WR(hw, RNP_VEB_MAC_LO(idx, vf_id), cfg->mac_lo);
+       RNP_E_REG_WR(hw, RNP_VEB_MAC_HI(idx, vf_id), cfg->mac_hi);
+       reg |= ((RNP_VEB_SWITCH_VF_EN | vf_id) << 8);
+       RNP_E_REG_WR(hw, RNP_VEB_VF_RING(idx, vf_id), reg);
+}
+
+void
+rnp_rxq_flow_disable(struct rnp_hw *hw,
+                    u16 hw_idx)
+{
+       u32 fc_ctrl;
+
+       spin_lock(&hw->rxq_reset_lock);
+       fc_ctrl = RNP_E_REG_RD(hw, RNP_RING_FC_EN(hw_idx));
+       wmb();
+       RNP_E_REG_WR(hw, RNP_RING_FC_THRESH(hw_idx), 0);
+       fc_ctrl |= 1 << (hw_idx % 32);
+       wmb();
+       RNP_E_REG_WR(hw, RNP_RING_FC_EN(hw_idx), fc_ctrl);
+}
+
+void
+rnp_rxq_flow_enable(struct rnp_hw *hw,
+                   u16 hw_idx)
+{
+       u32 fc_ctrl;
+
+
+       fc_ctrl = RNP_E_REG_RD(hw, RNP_RING_FC_EN(hw_idx));
+       fc_ctrl &= ~(1 << (hw_idx % 32));
+       wmb();
+       RNP_E_REG_WR(hw, RNP_RING_FC_EN(hw_idx), fc_ctrl);
+
+       spin_unlock(&hw->rxq_reset_lock);
+}
+
+#define RNP_RXQ_RESET_PKT_LEN  (64)
+
+static void
+rnp_reset_xmit(struct rnp_tx_queue *txq, u64 pkt_addr)
+{
+       volatile struct rnp_tx_desc *txbd;
+       struct rnp_txsw_entry *tx_entry;
+       u16 timeout = 0;
+       u16 tx_id;
+
+       tx_id = txq->tx_tail;
+       txbd = &txq->tx_bdr[tx_id];
+       tx_entry = &txq->sw_ring[tx_id];
+       memset(tx_entry, 0, sizeof(*tx_entry));
+
+       txbd->d.addr = pkt_addr;
+       txbd->d.blen = RNP_RXQ_RESET_PKT_LEN;
+       wmb();
+       txbd->d.cmd = cpu_to_le16(RNP_CMD_EOP | RNP_CMD_RS);
+       tx_id = (tx_id + 1) & txq->attr.nb_desc_mask;
+       wmb();
+       RNP_REG_WR(txq->tx_tailreg, 0, tx_id);
+       do {
+               if (txbd->d.cmd & RNP_CMD_DD)
+                       break;
+               if (timeout == 1000)
+                       RNP_PMD_ERR("rx queue %u reset send pkt is hang\n",
+                                       txq->attr.index);
+               timeout++;
+               udelay(10);
+       } while (1);
+}
+
+void
+rnp_reset_hw_rxq_op(struct rnp_hw *hw,
+                   struct rnp_rx_queue *rxq,
+                   struct rnp_tx_queue *txq,
+                   struct rnp_rxq_reset_res *res)
+{
+       u8 reset_pcap[RNP_RXQ_RESET_PKT_LEN] = {
+               0x01, 0x02, 0x27, 0xe2, 0x9f, 0xa6, 0x08, 0x00,
+               0x27, 0xfc, 0x6a, 0xc9, 0x08, 0x00, 0x45, 0x00,
+               0x01, 0xc4, 0xb5, 0xd0, 0x00, 0x7a, 0x40, 0x01,
+               0xbc, 0xea, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01,
+               0x01, 0x01, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
+               0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5,
+               0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd,
+               0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5};
+       struct rnp_veb_cfg veb_bak_cfg[RNP_MAX_PORT_OF_PF];
+       struct rnp_veb_cfg reset_cfg = {0};
+       volatile struct rnp_rx_desc *rxbd;
+       u16 index = rxq->attr.index;
+       u16 vf_num = hw->mbx.vf_num;
+       u8 *macaddr = res->eth_hdr;
+       u16 timeout = 0;
+       u16 vf_id = 0;
+       u16 head = 0;
+       u16 idx = 0;
+
+       memcpy(macaddr, reset_pcap, RNP_RXQ_RESET_PKT_LEN);
+       macaddr[5] = index;
+       reset_cfg.mac_hi = RNP_GET_MAC_HI(macaddr);
+       reset_cfg.mac_lo = RNP_GET_MAC_LO(macaddr);
+       reset_cfg.ring = index;
+       vf_id = (vf_num != UINT16_MAX) ? vf_num : index / 2;
+       if (hw->mbx.vf_num == UINT16_MAX) {
+               for (idx = 0; idx < RNP_MAX_PORT_OF_PF; idx++) {
+                       rnp_read_mac_veb(hw, idx, vf_id, &veb_bak_cfg[idx]);
+                       rnp_update_mac_veb(hw, idx, vf_id, &reset_cfg);
+               }
+       } else {
+               idx = rxq->attr.lane_id;
+               rnp_read_mac_veb(hw, idx, vf_id, &veb_bak_cfg[idx]);
+               rnp_update_mac_veb(hw, idx, vf_id, &reset_cfg);
+       }
+       wmb();
+       timeout = 0;
+       do {
+               if (!RNP_E_REG_RD(hw, RNP_RXQ_READY(index)))
+                       break;
+               udelay(5);
+               timeout++;
+       } while (timeout < 100);
+       timeout = 0;
+       do {
+               if (RNP_E_REG_RD(hw, RNP_TXQ_READY(index)))
+                       break;
+               udelay(10);
+               timeout++;
+       } while (timeout < 100);
+       rxq->rx_tail = RNP_E_REG_RD(hw, RNP_RXQ_HEAD(index));
+       rxbd = &rxq->rx_bdr[rxq->rx_tail];
+       rxbd->d.pkt_addr = res->rx_pkt_addr;
+       if (rxq->rx_tail != rxq->attr.nb_desc_mask)
+               RNP_E_REG_WR(hw, RNP_RXQ_LEN(index), rxq->rx_tail + 1);
+       wmb();
+       RNP_REG_WR(rxq->rx_tailreg, 0, 0);
+       RNP_E_REG_WR(hw, RNP_RXQ_START(index), TRUE);
+       rnp_reset_xmit(txq, res->tx_pkt_addr);
+       timeout = 0;
+       do {
+               if (rxbd->wb.qword1.cmd & cpu_to_le32(RNP_CMD_DD))
+                       break;
+               if (timeout == 1000)
+                       RNP_PMD_LOG(ERR, "rx_queue[%d] reset queue hang\n",
+                                       index);
+               udelay(10);
+               timeout++;
+       } while (1);
+       timeout = 0;
+       do {
+               head = RNP_E_REG_RD(hw, RNP_RXQ_HEAD(index));
+               if (head == 0)
+                       break;
+               timeout++;
+               if (timeout == 1000)
+                       RNP_PMD_LOG(ERR, "rx_queue[%d] reset head to 0 failed",
+                                       index);
+               udelay(10);
+       } while (1);
+       RNP_E_REG_WR(hw, RNP_RXQ_START(index), FALSE);
+       rxbd->d.pkt_addr = 0;
+       rxbd->d.cmd = 0;
+       if (hw->mbx.vf_num == UINT16_MAX) {
+               for (idx = 0; idx < 4; idx++)
+                       rnp_update_mac_veb(hw, idx, vf_id, &veb_bak_cfg[idx]);
+       } else {
+               idx = rxq->attr.lane_id;
+               rnp_update_mac_veb(hw, idx, vf_id, &veb_bak_cfg[idx]);
+       }
+       rxq->rx_tail = head;
+}
+
+void rnp_setup_rxbdr(struct rnp_hw *hw,
+                    struct rnp_rx_queue *rxq)
+{
+       u16 max_desc = rxq->attr.nb_desc;
+       u16 idx = rxq->attr.index;
+       phys_addr_t bd_address;
+       u32 dmah, dmal;
+       u32 desc_ctrl;
+
+       RNP_E_REG_WR(hw, RNP_RXQ_START(idx), FALSE);
+       bd_address = (phys_addr_t)rxq->ring_phys_addr;
+       dmah = upper_32_bits((uint64_t)bd_address);
+       dmal = lower_32_bits((uint64_t)bd_address);
+       desc_ctrl = rxq->pburst << RNQ_DESC_FETCH_BURST_S | rxq->pthresh;
+       if (hw->mbx.sriov_st)
+               dmah |= (hw->mbx.sriov_st << 24);
+       /* we must set sriov_state to hi dma_address high 8bit for vf isolation
+        * |---8bit-----|----------24bit--------|
+        * |sriov_state-|-------high dma address|
+        * |---------------8bit-----------------|
+        * |7bit | 6bit |5-0bit-----------------|
+        * |vf_en|pf_num|-------vf_num----------|
+        */
+       RNP_E_REG_WR(hw, RNP_RXQ_BASE_ADDR_LO(idx), dmal);
+       RNP_E_REG_WR(hw, RNP_RXQ_BASE_ADDR_HI(idx), dmah);
+       RNP_E_REG_WR(hw, RNP_RXQ_LEN(idx), max_desc);
+       rxq->rx_tailreg = (u32 *)((u8 *)hw->e_ctrl + RNP_RXQ_TAIL(idx));
+       rxq->rx_headreg = (u32 *)((u8 *)hw->e_ctrl + RNP_RXQ_HEAD(idx));
+       rxq->rx_tail = RNP_E_REG_RD(hw, RNP_RXQ_HEAD(idx));
+       RNP_E_REG_WR(hw, RNP_RXQ_DESC_FETCH_CTRL(idx), desc_ctrl);
+       RNP_E_REG_WR(hw, RNP_RXQ_DROP_TIMEOUT_TH(idx),
+                       rxq->nodesc_tm_thresh);
+}
+
+int rnp_get_dma_ring_index(struct rnp_eth_port *port, u16 queue_idx)
+{
+       struct rnp_hw *hw = port->hw;
+       u16 lane = port->attr.nr_lane;
+       u16 hwrid = 0;
+
+       switch (hw->nic_mode) {
+       case RNP_DUAL_10G:
+               hwrid = 2 * (queue_idx + lane) - queue_idx % 2;
+               break;
+       case RNP_QUAD_10G:
+               hwrid = 4 * (queue_idx) + lane;
+               break;
+       default:
+               hwrid = queue_idx;
+       }
+
+       return hwrid;
+}
+
+void rnp_setup_txbdr(struct rnp_hw *hw, struct rnp_tx_queue *txq)
+{
+       u16 max_desc = txq->attr.nb_desc;
+       u16 idx = txq->attr.index;
+       phys_addr_t bd_address;
+       u32 desc_ctrl = 0;
+       u32 dmah, dmal;
+
+       bd_address = (phys_addr_t)txq->ring_phys_addr;
+       desc_ctrl = txq->pburst << RNQ_DESC_FETCH_BURST_S | txq->pthresh;
+       dmah = upper_32_bits((u64)bd_address);
+       dmal = lower_32_bits((u64)bd_address);
+       if (hw->mbx.sriov_st)
+               dmah |= (hw->mbx.sriov_st << 24);
+       /* We must set sriov_state to hi dma_address high 8bit for vf isolation
+        * |---8bit-----|----------24bit--------|
+        * |sriov_state-|-------high dma address|
+        * |---------------8bit-----------------|
+        * |7bit | 6bit |5-0bit-----------------|
+        * |vf_en|pf_num|-------vf_num----------|
+        */
+       RNP_E_REG_WR(hw, RNP_TXQ_BASE_ADDR_LO(idx), dmal);
+       RNP_E_REG_WR(hw, RNP_TXQ_BASE_ADDR_HI(idx), dmah);
+       RNP_E_REG_WR(hw, RNP_TXQ_LEN(idx), max_desc);
+       RNP_E_REG_WR(hw, RNP_TXQ_DESC_FETCH_CTRL(idx), desc_ctrl);
+       RNP_E_REG_WR(hw, RNP_RXTX_IRQ_MASK(idx), RNP_RXTX_IRQ_MASK_ALL);
+       txq->tx_headreg = (void *)((u8 *)hw->e_ctrl + RNP_TXQ_HEAD(idx));
+       txq->tx_tailreg = (void *)((u8 *)hw->e_ctrl + RNP_TXQ_TAIL(idx));
+
+       txq->tx_tail = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(idx));
+       RNP_E_REG_WR(hw, RNP_TXQ_TAIL(idx), 0);
+}
+
+static void
+rnp_txq_reset_pre(struct rnp_hw *hw)
+{
+       u16 i = 0;
+
+       spin_lock(&hw->txq_reset_lock);
+       for (i = 0; i < RNP_MAX_RX_QUEUE_NUM; i++) {
+               wmb();
+               RNP_E_REG_WR(hw, RNP_RXQ_START(i), 0);
+       }
+}
+
+static void
+rnp_txq_reset_fin(struct rnp_hw *hw)
+{
+       u16 i = 0;
+
+       for (i = 0; i < RNP_MAX_RX_QUEUE_NUM; i++) {
+               wmb();
+               RNP_E_REG_WR(hw, RNP_RXQ_START(i), 1);
+       }
+       spin_unlock(&hw->txq_reset_lock);
+}
+
+static void
+rnp_xmit_nop_frame_ring(struct rnp_hw *hw,
+                       struct rnp_tx_queue *txq,
+                       u16 head)
+{
+       volatile struct rnp_tx_desc *tx_desc;
+       u16 check_head = 0;
+       u16 timeout = 0;
+       u16 index = 0;
+       u16 tx_id;
+
+       tx_id = head;
+       index = txq->attr.index;
+       tx_desc = &txq->tx_bdr[tx_id];
+
+       /* set length to 0 */
+       tx_desc->d.blen = 0;
+       tx_desc->d.addr = 0;
+       wmb();
+       tx_desc->d.cmd = cpu_to_le16(RNP_CMD_EOP);
+       wmb();
+       /* update tail */
+       RNP_REG_WR(txq->tx_tailreg, 0, 0);
+       do {
+               check_head = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(index));
+               if (check_head == 0)
+                       break;
+               if (timeout == 1000)
+                       RNP_PMD_ERR("tx_queue[%d] reset may be hang "
+                                       "check_head %d base head %d\n",
+                                       index, check_head, head);
+               timeout++;
+               udelay(10);
+       } while (1);
+       /* restore the origin right state */
+       wmb();
+       RNP_E_REG_WR(hw, RNP_TXQ_LEN(index), txq->attr.nb_desc);
+}
+
+void rnp_reset_hw_txq_op(struct rnp_hw *hw,
+                        struct rnp_tx_queue *txq)
+{
+       u16 timeout = 0;
+       u16 index = 0;
+       u16 head;
+       u16 tail;
+
+       timeout = 0;
+       /* Disable Tx Queue */
+       index = txq->attr.index;
+       rnp_txq_reset_pre(hw);
+       rmb();
+       tail = RNP_E_REG_RD(hw, RNP_TXQ_TAIL(index));
+       txq->tx_tail = tail;
+       do {
+               /* wait for hw head is stopped */
+               head = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(index));
+               if (head == txq->tx_tail)
+                       break;
+               if (timeout > 1000) {
+                       RNP_PMD_ERR("txq[%u] 1000*10us can't "
+                                   "wait for hw head == tail\n", index);
+                       break;
+               }
+               udelay(10);
+       } while (1);
+       rmb();
+       head = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(index));
+       /* head is zero no need to reset */
+       if (head == 0)
+               goto tx_reset_fin;
+       wmb();
+       if (head != txq->attr.nb_desc_mask)
+               RNP_E_REG_WR(hw, RNP_TXQ_LEN(index), head + 1);
+       wmb();
+       /* reset hw head */
+       rnp_xmit_nop_frame_ring(hw, txq, head);
+       rmb();
+       txq->tx_tail = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(index));
+tx_reset_fin:
+       rnp_txq_reset_fin(hw);
+}
diff --git a/drivers/net/rnp/base/rnp_bdq_if.h 
b/drivers/net/rnp/base/rnp_bdq_if.h
new file mode 100644
index 0000000..61a3832
--- /dev/null
+++ b/drivers/net/rnp/base/rnp_bdq_if.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Mucse IC Design Ltd.
+ */
+
+#ifndef _RNP_BDQ_IF_H_
+#define _RNP_BDQ_IF_H_
+
+#include "rnp_hw.h"
+
+struct rnp_rx_queue;
+struct rnp_tx_queue;
+#pragma pack(push)
+#pragma pack(1)
+/* receive descriptor */
+struct rnp_rx_desc {
+       /* rx buffer descriptor */
+       union {
+               struct {
+                       u64 pkt_addr;
+                       u16 rsvd[3];
+                       u16 cmd;
+               } d;
+               struct {
+                       struct {
+                               u32 rss_hash;
+                               u32 mark_data;
+                       } qword0;
+                       struct {
+                               u32 lens;
+                               u16 vlan_tci;
+                               u16 cmd;
+                       } qword1;
+               } wb;
+       };
+};
+/* tx buffer descriptors (BD) */
+struct rnp_tx_desc {
+       union {
+               struct {
+                       u64 addr;       /* pkt dma address */
+                       u16 blen;       /* pkt data Len */
+                       u16 mac_ip_len; /* mac ip header len */
+                       u16 vlan_tci;   /* vlan_tci */
+                       u16 cmd;        /* ctrl command */
+               } d;
+               struct {
+                       struct {
+                               u16 mss;        /* tso sz */
+                               u8 vf_num;      /* vf num */
+                               u8 l4_len;      /* l4 header size */
+                               u8 tunnel_len;  /* tunnel header size */
+                               u16 vlan_tci;   /* vlan_tci */
+                               u8 veb_tran;    /* mark pkt is transmit by veb 
*/
+                       } qword0;
+                       struct {
+                               u16 rsvd[3];
+                               u16 cmd;        /* ctrl command */
+                       } qword1;
+               } c;
+       };
+};
+#pragma pack(pop)
+/* common command */
+#define RNP_CMD_EOP              RTE_BIT32(0) /* End Of Packet */
+#define RNP_CMD_DD               RTE_BIT32(1)
+#define RNP_CMD_RS               RTE_BIT32(2)
+#define RNP_DESC_TYPE_S                (3)
+#define RNP_DATA_DESC          (0x00UL << RNP_DESC_TYPE_S)
+#define RNP_CTRL_DESC          (0x01UL << RNP_DESC_TYPE_S)
+/* rx data cmd */
+#define RNP_RX_PTYPE_PTP       RTE_BIT32(4)
+#define RNP_RX_L3TYPE_S                (5)
+#define RNP_RX_L3TYPE_IPV4     (0x00UL << RNP_RX_L3TYPE_S)
+#define RNP_RX_L3TYPE_IPV6     (0x01UL << RNP_RX_L3TYPE_S)
+#define RNP_RX_L4TYPE_S                (6)
+#define RNP_RX_L4TYPE_TCP      (0x01UL << RNP_RX_L4TYPE_S)
+#define RNP_RX_L4TYPE_SCTP     (0x02UL << RNP_RX_L4TYPE_S)
+#define RNP_RX_L4TYPE_UDP      (0x03UL << RNP_RX_L4TYPE_S)
+#define RNP_RX_ERR_MASK                RTE_GENMASK32(12, 8)
+#define RNP_RX_L3_ERR          RTE_BIT32(8)
+#define RNP_RX_L4_ERR          RTE_BIT32(9)
+#define RNP_RX_SCTP_ERR                RTE_BIT32(10)
+#define RNP_RX_IN_L3_ERR       RTE_BIT32(11)
+#define RNP_RX_IN_L4_ERR       RTE_BIT32(12)
+#define RNP_RX_TUNNEL_TYPE_S   (13)
+#define RNP_RX_PTYPE_VXLAN     (0x01UL << RNP_RX_TUNNEL_TYPE_S)
+#define RNP_RX_PTYPE_NVGRE     (0x02UL << RNP_RX_TUNNEL_TYPE_S)
+#define RNP_RX_PTYPE_VLAN      RTE_BIT32(15)
+/* tx data cmd */
+#define RNP_TX_TSO_EN          RTE_BIT32(4)
+#define RNP_TX_L3TYPE_S                (5)
+#define RNP_TX_L3TYPE_IPV6     (0x01UL << RNP_TX_L3TYPE_S)
+#define RNP_TX_L3TYPE_IPV4     (0x00UL << RNP_TX_L3TYPE_S)
+#define RNP_TX_L4TYPE_S                (6)
+#define RNP_TX_L4TYPE_TCP      (0x01UL << RNP_TX_L4TYPE_S)
+#define RNP_TX_L4TYPE_SCTP     (0x02UL << RNP_TX_L4TYPE_S)
+#define RNP_TX_L4TYPE_UDP      (0x03UL << RNP_TX_L4TYPE_S)
+#define RNP_TX_TUNNEL_TYPE_S   (8)
+#define RNP_TX_VXLAN_TUNNEL    (0x01UL << RNP_TX_TUNNEL_TYPE_S)
+#define RNP_TX_NVGRE_TUNNEL    (0x02UL << RNP_TX_TUNNEL_TYPE_S)
+#define RNP_TX_PTP_EN          RTE_BIT32(10)
+#define RNP_TX_IP_CKSUM_EN     RTE_BIT32(11)
+#define RNP_TX_L4CKSUM_EN      RTE_BIT32(12)
+#define RNP_TX_VLAN_CTRL_S     (13)
+#define RNP_TX_VLAN_STRIP      (0x01UL << RNP_TX_VLAN_CTRL_S)
+#define RNP_TX_VLAN_INSERT     (0x02UL << RNP_TX_VLAN_CTRL_S)
+#define RNP_TX_VLAN_VALID      RTE_BIT32(15)
+/* tx data mac_ip len */
+#define RNP_TX_MAC_LEN_S       (9)
+/* tx ctrl cmd */
+#define RNP_TX_LEN_PAD_S       (8)
+#define RNP_TX_OFF_MAC_PAD     (0x01UL << RNP_TX_LEN_PAD_S)
+#define RNP_TX_QINQ_CTRL_S     (10)
+#define RNP_TX_QINQ_INSERT     (0x02UL << RNP_TX_QINQ_CTRL_S)
+#define RNP_TX_QINQ_STRIP      (0x01UL << RNP_TX_QINQ_CTRL_S)
+#define RNP_TX_TO_NPU_EN       RTE_BIT32(15)
+/* descript op end */
+struct rnp_rxq_reset_res {
+       u64 rx_pkt_addr;
+       u64 tx_pkt_addr;
+       u8 *eth_hdr;
+};
+struct rnp_veb_cfg {
+       uint32_t mac_hi;
+       uint32_t mac_lo;
+       uint32_t vid;
+       uint16_t vf_id;
+       uint16_t ring;
+};
+void
+rnp_rxq_flow_enable(struct rnp_hw *hw,
+                   u16 hw_idx);
+void
+rnp_rxq_flow_disable(struct rnp_hw *hw,
+                    u16 hw_idx);
+void
+rnp_reset_hw_rxq_op(struct rnp_hw *hw,
+                   struct rnp_rx_queue *rxq,
+                   struct rnp_tx_queue *txq,
+                   struct rnp_rxq_reset_res *res);
+void rnp_reset_hw_txq_op(struct rnp_hw *hw,
+                        struct rnp_tx_queue *txq);
+void rnp_setup_rxbdr(struct rnp_hw *hw,
+                    struct rnp_rx_queue *rxq);
+void rnp_setup_txbdr(struct rnp_hw *hw,
+                    struct rnp_tx_queue *txq);
+int rnp_get_dma_ring_index(struct rnp_eth_port *port, u16 queue_idx);
+
+#endif /* _RNP_BDQ_IF_H_ */
diff --git a/drivers/net/rnp/base/rnp_common.h 
b/drivers/net/rnp/base/rnp_common.h
index aaf77a6..bd00708 100644
--- a/drivers/net/rnp/base/rnp_common.h
+++ b/drivers/net/rnp/base/rnp_common.h
@@ -6,6 +6,10 @@
 #define _RNP_COMMON_H_
 
 #define RNP_NIC_RESET          _NIC_(0x0010)
+#define RNP_GET_MAC_HI(mac_addr) (((macaddr[0]) << 8) | (macaddr[1]))
+#define RNP_GET_MAC_LO(mac_addr) \
+       ((macaddr[2] << 24) | (macaddr[3] << 16) | \
+        ((macaddr[4] << 8)) | (macaddr[5]))
 int rnp_init_hw(struct rnp_hw *hw);
 int rnp_setup_common_ops(struct rnp_hw *hw);
 
diff --git a/drivers/net/rnp/base/rnp_dma_regs.h 
b/drivers/net/rnp/base/rnp_dma_regs.h
index 00f8aff..3664c0a 100644
--- a/drivers/net/rnp/base/rnp_dma_regs.h
+++ b/drivers/net/rnp/base/rnp_dma_regs.h
@@ -9,5 +9,50 @@
 #define RNP_DMA_HW_EN          (0x10)
 #define RNP_DMA_EN_ALL         (0b1111)
 #define RNP_DMA_HW_STATE       (0x14)
+/* --- queue register --- */
+/* queue enable */
+#define RNP_RXQ_START(qid)     _RING_(0x0010 + 0x100 * (qid))
+#define RNP_RXQ_READY(qid)     _RING_(0x0014 + 0x100 * (qid))
+#define RNP_TXQ_START(qid)     _RING_(0x0018 + 0x100 * (qid))
+#define RNP_TXQ_READY(qid)     _RING_(0x001c + 0x100 * (qid))
+/* queue irq generate ctrl */
+#define RNP_RXTX_IRQ_STAT(qid) _RING_(0x0020 + 0x100 * (qid))
+#define RNP_RXTX_IRQ_MASK(qid) _RING_(0x0024 + 0x100 * (qid))
+#define RNP_TX_IRQ_MASK                RTE_BIT32(1)
+#define RNP_RX_IRQ_MASK                RTE_BIT32(0)
+#define RNP_RXTX_IRQ_MASK_ALL  (RNP_RX_IRQ_MASK | RNP_TX_IRQ_MASK)
+#define RNP_RXTX_IRQ_CLER(qid) _RING_(0x0028 + 0x100 * (qid))
+/* rx-queue setup */
+#define RNP_RXQ_BASE_ADDR_HI(qid)      _RING_(0x0030 + 0x100 * (qid))
+#define RNP_RXQ_BASE_ADDR_LO(qid)      _RING_(0x0034 + 0x100 * (qid))
+#define RNP_RXQ_LEN(qid)               _RING_(0x0038 + 0x100 * (qid))
+#define RNP_RXQ_HEAD(qid)              _RING_(0x003c + 0x100 * (qid))
+#define RNP_RXQ_TAIL(qid)              _RING_(0x0040 + 0x100 * (qid))
+#define RNP_RXQ_DESC_FETCH_CTRL(qid)   _RING_(0x0044 + 0x100 * (qid))
+/* rx queue interrupt generate pararm */
+#define RNP_RXQ_INT_DELAY_TIMER(qid)   _RING_(0x0048 + 0x100 * (qid))
+#define RNP_RXQ_INT_DELAY_PKTCNT(qidx) _RING_(0x004c + 0x100 * (qid))
+#define RNP_RXQ_RX_PRI_LVL(qid)                _RING_(0x0050 + 0x100 * (qid))
+#define RNP_RXQ_DROP_TIMEOUT_TH(qid)   _RING_(0x0054 + 0x100 * (qid))
+/* tx queue setup */
+#define RNP_TXQ_BASE_ADDR_HI(qid)        _RING_(0x0060 + 0x100 * (qid))
+#define RNP_TXQ_BASE_ADDR_LO(qid)        _RING_(0x0064 + 0x100 * (qid))
+#define RNP_TXQ_LEN(qid)                 _RING_(0x0068 + 0x100 * (qid))
+#define RNP_TXQ_HEAD(qid)                _RING_(0x006c + 0x100 * (qid))
+#define RNP_TXQ_TAIL(qid)                _RING_(0x0070 + 0x100 * (qid))
+#define RNP_TXQ_DESC_FETCH_CTRL(qid)     _RING_(0x0074 + 0x100 * (qid))
+#define RNQ_DESC_FETCH_BURST_S         (16)
+/* tx queue interrupt generate pararm */
+#define RNP_TXQ_INT_DELAY_TIMER(qid)     _RING_(0x0078 + 0x100 * (qid))
+#define RNP_TXQ_INT_DELAY_PKTCNT(qid)    _RING_(0x007c + 0x100 * (qid))
+/* veb ctrl register */
+#define RNP_VEB_MAC_LO(p, n)   _RING_(0x00a0 + (4 * (p)) + (0x100 * (n)))
+#define RNP_VEB_MAC_HI(p, n)   _RING_(0x00b0 + (4 * (p)) + (0x100 * (n)))
+#define RNP_VEB_VID_CFG(p, n)  _RING_(0x00c0 + (4 * (p)) + (0x100 * (n)))
+#define RNP_VEB_VF_RING(p, n)  _RING_(0x00d0 + (4 * (p)) + (0x100 * (n)))
+#define RNP_MAX_VEB_TB         (64)
+#define RNP_VEB_RING_CFG_S     (8)
+#define RNP_VEB_SWITCH_VF_EN   RTE_BIT32(7)
+#define MAX_VEB_TABLES_NUM     (4)
 
 #endif /* _RNP_DMA_REGS_H_ */
diff --git a/drivers/net/rnp/base/rnp_eth_regs.h 
b/drivers/net/rnp/base/rnp_eth_regs.h
index c4519ba..10e3d95 100644
--- a/drivers/net/rnp/base/rnp_eth_regs.h
+++ b/drivers/net/rnp/base/rnp_eth_regs.h
@@ -10,6 +10,10 @@
 #define RNP_E_FILTER_EN                _ETH_(0x801c)
 #define RNP_E_REDIR_EN         _ETH_(0x8030)
 
+/* rx queue flow ctrl */
+#define RNP_RX_FC_ENABLE       _ETH_(0x8520)
+#define RNP_RING_FC_EN(n)      _ETH_(0x8524 + ((0x4) * ((n) / 32)))
+#define RNP_RING_FC_THRESH(n)  _ETH_(0x8a00 + ((0x4) * (n)))
 /* Mac Host Filter  */
 #define RNP_MAC_FCTRL          _ETH_(0x9110)
 #define RNP_MAC_FCTRL_MPE      RTE_BIT32(8)  /* Multicast Promiscuous En */
diff --git a/drivers/net/rnp/base/rnp_hw.h b/drivers/net/rnp/base/rnp_hw.h
index 1b31362..4f5a73e 100644
--- a/drivers/net/rnp/base/rnp_hw.h
+++ b/drivers/net/rnp/base/rnp_hw.h
@@ -120,6 +120,9 @@ struct rnp_hw {
        bool lane_is_sgmii[RNP_MAX_PORT_OF_PF];
        struct rnp_mbx_info mbx;
        struct rnp_fw_info fw_info;
+
+       spinlock_t rxq_reset_lock;
+       spinlock_t txq_reset_lock;
 };
 
 #endif /* __RNP_H__*/
diff --git a/drivers/net/rnp/base/rnp_osdep.h b/drivers/net/rnp/base/rnp_osdep.h
index 03f6c51..137e0e8 100644
--- a/drivers/net/rnp/base/rnp_osdep.h
+++ b/drivers/net/rnp/base/rnp_osdep.h
@@ -14,6 +14,7 @@
 #include <rte_bitops.h>
 #include <rte_cycles.h>
 #include <rte_byteorder.h>
+#include <rte_spinlock.h>
 #include <rte_common.h>
 #include <rte_memcpy.h>
 #include <rte_memzone.h>
@@ -32,16 +33,28 @@
 
 #define mb()   rte_mb()
 #define wmb()  rte_wmb()
+#define rmb()  rte_rmb()
 
 #define udelay(x) rte_delay_us(x)
 #define mdelay(x) rte_delay_ms(x)
 #define memcpy rte_memcpy
 
+#ifndef upper_32_bits
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+#define lower_32_bits(n) ((u32)((n) & 0xffffffff))
+#endif
+
+#ifndef cpu_to_le32
+#define cpu_to_le16(v) rte_cpu_to_le_16((u16)(v))
+#define cpu_to_le32(v) rte_cpu_to_le_32((u32)(v))
+#endif
+
 #define spinlock_t                     rte_spinlock_t
 #define spin_lock_init(spinlock_v)     rte_spinlock_init(spinlock_v)
 #define spin_lock(spinlock_v)          rte_spinlock_lock(spinlock_v)
 #define spin_unlock(spinlock_v)                rte_spinlock_unlock(spinlock_v)
 
+#define _RING_(off)    ((off) + (0x08000))
 #define _ETH_(off)     ((off) + (0x10000))
 #define _NIC_(off)     ((off) + (0x30000))
 #define _MAC_(off)     ((off) + (0x60000))
diff --git a/drivers/net/rnp/meson.build b/drivers/net/rnp/meson.build
index 29e6d49..ff3dc41 100644
--- a/drivers/net/rnp/meson.build
+++ b/drivers/net/rnp/meson.build
@@ -14,4 +14,5 @@ includes += include_directories('base')
 
 sources = files(
                'rnp_ethdev.c',
+               'rnp_rxtx.c',
 )
diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index 19ef493..ab7bd60 100644
--- a/drivers/net/rnp/rnp.h
+++ b/drivers/net/rnp/rnp.h
@@ -105,6 +105,7 @@ struct rnp_eth_port {
        struct rte_ether_addr mac_addr;
        struct rte_eth_dev *eth_dev;
        struct rnp_port_attr attr;
+       struct rnp_tx_queue *tx_queues[RNP_MAX_RX_QUEUE_NUM];
        struct rnp_hw *hw;
 };
 
@@ -113,6 +114,7 @@ struct rnp_eth_adapter {
        struct rte_pci_device *pdev;
        struct rte_eth_dev *eth_dev; /* alloc eth_dev by platform */
 
+       struct rte_mempool *reset_pool;
        struct rnp_eth_port *ports[RNP_MAX_PORT_OF_PF];
        uint16_t closed_ports;
        uint16_t inited_ports;
diff --git a/drivers/net/rnp/rnp_ethdev.c b/drivers/net/rnp/rnp_ethdev.c
index 13d949a..d5e5ef7 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -14,6 +14,7 @@
 #include "base/rnp_mbx_fw.h"
 #include "base/rnp_mac.h"
 #include "base/rnp_common.h"
+#include "rnp_rxtx.h"
 
 static struct rte_eth_dev *
 rnp_alloc_eth_port(struct rte_pci_device *pci, char *name)
@@ -237,6 +238,11 @@ static int rnp_allmulticast_disable(struct rte_eth_dev 
*eth_dev)
        .promiscuous_disable          = rnp_promiscuous_disable,
        .allmulticast_enable          = rnp_allmulticast_enable,
        .allmulticast_disable         = rnp_allmulticast_disable,
+
+       .rx_queue_setup               = rnp_rx_queue_setup,
+       .rx_queue_release             = rnp_dev_rx_queue_release,
+       .tx_queue_setup               = rnp_tx_queue_setup,
+       .tx_queue_release             = rnp_dev_tx_queue_release,
 };
 
 static void
@@ -330,6 +336,26 @@ static int rnp_allmulticast_disable(struct rte_eth_dev 
*eth_dev)
 }
 
 static int
+rnp_rx_reset_pool_setup(struct rnp_eth_adapter *adapter)
+{
+       struct rte_eth_dev *eth_dev = adapter->eth_dev;
+       char name[RTE_MEMPOOL_NAMESIZE];
+
+       snprintf(name, sizeof(name), "rx_reset_pool_%d:%d",
+                       eth_dev->data->port_id, eth_dev->device->numa_node);
+
+       adapter->reset_pool = rte_pktmbuf_pool_create(name, 2,
+                       0, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+                       eth_dev->device->numa_node);
+       if (adapter->reset_pool == NULL) {
+               RNP_PMD_ERR("mempool %s create failed", name);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int
 rnp_eth_dev_init(struct rte_eth_dev *eth_dev)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
@@ -424,6 +450,9 @@ static int rnp_allmulticast_disable(struct rte_eth_dev 
*eth_dev)
                        rte_eth_dev_probing_finish(sub_eth_dev);
                }
        }
+       ret = rnp_rx_reset_pool_setup(adapter);
+       if (ret)
+               goto eth_alloc_error;
        /* enable link update event interrupt */
        rte_intr_callback_register(intr_handle,
                        rnp_dev_interrupt_handler, adapter);
diff --git a/drivers/net/rnp/rnp_rxtx.c b/drivers/net/rnp/rnp_rxtx.c
new file mode 100644
index 0000000..3c34f23
--- /dev/null
+++ b/drivers/net/rnp/rnp_rxtx.c
@@ -0,0 +1,476 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Mucse IC Design Ltd.
+ */
+
+#include <stdint.h>
+
+#include <rte_ethdev.h>
+#include <rte_memzone.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+
+#include "base/rnp_bdq_if.h"
+#include "base/rnp_dma_regs.h"
+#include "rnp_rxtx.h"
+#include "rnp_logs.h"
+#include "rnp.h"
+
+static void rnp_tx_queue_release_mbuf(struct rnp_tx_queue *txq);
+static void rnp_tx_queue_sw_reset(struct rnp_tx_queue *txq);
+static void rnp_tx_queue_release(void *_txq);
+
+static __rte_always_inline phys_addr_t
+rnp_get_dma_addr(struct rnp_queue_attr *attr, struct rte_mbuf *mbuf)
+{
+       phys_addr_t dma_addr;
+
+       dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova(mbuf));
+       if (attr->sriov_st)
+               dma_addr |= (attr->sriov_st << 56);
+
+       return dma_addr;
+}
+
+static void rnp_rx_queue_release_mbuf(struct rnp_rx_queue *rxq)
+{
+       uint16_t i;
+
+       if (!rxq)
+               return;
+
+       if (rxq->sw_ring) {
+               for (i = 0; i < rxq->attr.nb_desc; i++) {
+                       if (rxq->sw_ring[i].mbuf)
+                               rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
+               }
+               memset(rxq->sw_ring, 0,
+                               sizeof(rxq->sw_ring[0]) * rxq->attr.nb_desc);
+       }
+}
+
+static void rnp_rx_queue_release(void *_rxq)
+{
+       struct rnp_rx_queue *rxq = (struct rnp_rx_queue *)_rxq;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (rxq) {
+               rnp_rx_queue_release_mbuf(rxq);
+               if (rxq->rz)
+                       rte_memzone_free(rxq->rz);
+               if (rxq->sw_ring)
+                       rte_free(rxq->sw_ring);
+               rte_free(rxq);
+       }
+}
+
+static int
+rnp_tx_queue_reset(struct rnp_eth_port *port,
+                  struct rnp_tx_queue *txq)
+{
+       struct rnp_hw *hw = port->hw;
+
+       rnp_reset_hw_txq_op(hw, txq);
+
+       return 0;
+}
+
+static int
+rnp_rx_queue_reset(struct rnp_eth_port *port,
+                  struct rnp_rx_queue *rxq)
+{
+       struct rte_eth_dev_data *data = port->eth_dev->data;
+       struct rnp_eth_adapter *adapter = port->hw->back;
+       struct rte_eth_dev *dev = port->eth_dev;
+       struct rnp_rxq_reset_res res = {0};
+       uint16_t qidx = rxq->attr.queue_id;
+       struct rnp_tx_queue *txq = NULL;
+       struct rte_eth_txconf def_conf;
+       struct rnp_hw *hw = port->hw;
+       struct rte_mbuf *m_mbuf[2];
+       bool tx_new = false;
+       uint16_t index;
+       int err = 0;
+
+       index = rxq->attr.index;
+       /* disable eth send pkts to this ring */
+       rxq->rx_tail = RNP_E_REG_RD(hw, RNP_RXQ_HEAD(index));
+       if (!rxq->rx_tail)
+               return 0;
+       if (qidx < data->nb_tx_queues && data->tx_queues[qidx]) {
+               txq = (struct rnp_tx_queue *)data->tx_queues[qidx];
+       } else {
+               /* tx queues has been release or txq num less than rxq num */
+               def_conf.tx_deferred_start = true;
+               def_conf.tx_free_thresh = 32;
+               def_conf.tx_rs_thresh = 32;
+               if (dev->dev_ops->tx_queue_setup)
+                       err = dev->dev_ops->tx_queue_setup(dev, qidx,
+                               rxq->attr.nb_desc,
+                               dev->data->numa_node, &def_conf);
+               if (err) {
+                       RNP_PMD_ERR("rxq[%d] reset pair txq setup fail", qidx);
+                       return err;
+               }
+               txq = port->tx_queues[qidx];
+               tx_new = true;
+       }
+       if (unlikely(rte_mempool_get_bulk(adapter->reset_pool, (void *)m_mbuf,
+                                       2) < 0)) {
+               RNP_PMD_LOG(WARNING, "port[%d] reset rx queue[%d] failed "
+                               "because mbuf alloc failed\n",
+                               data->port_id, qidx);
+               return -ENOMEM;
+       }
+       rnp_rxq_flow_disable(hw, index);
+       rte_mbuf_refcnt_set(m_mbuf[0], 1);
+       rte_mbuf_refcnt_set(m_mbuf[1], 1);
+       m_mbuf[0]->data_off = RTE_PKTMBUF_HEADROOM;
+       m_mbuf[1]->data_off = RTE_PKTMBUF_HEADROOM;
+       res.eth_hdr = rte_pktmbuf_mtod(m_mbuf[0], uint8_t *);
+       res.rx_pkt_addr = rnp_get_dma_addr(&rxq->attr, m_mbuf[1]);
+       res.tx_pkt_addr = rnp_get_dma_addr(&txq->attr, m_mbuf[0]);
+       rnp_reset_hw_rxq_op(hw, rxq, txq, &res);
+       if (tx_new)
+               rnp_tx_queue_release(txq);
+       else
+               txq->tx_tail = RNP_E_REG_RD(hw, RNP_TXQ_HEAD(index));
+       if (!tx_new) {
+               if (txq->tx_tail) {
+                       rnp_tx_queue_release_mbuf(txq);
+                       rnp_tx_queue_reset(port, txq);
+                       rnp_tx_queue_sw_reset(txq);
+               }
+       }
+       rte_mempool_put_bulk(adapter->reset_pool, (void **)m_mbuf, 2);
+       rnp_rxq_flow_enable(hw, index);
+       rte_io_wmb();
+       RNP_E_REG_WR(hw, RNP_RXQ_LEN(index), rxq->attr.nb_desc);
+
+       return 0;
+}
+
+static int
+rnp_alloc_rxbdr(struct rte_eth_dev *dev,
+               struct rnp_rx_queue *rxq,
+               uint16_t nb_rx_desc, int socket_id)
+{
+       const struct rte_memzone *rz = NULL;
+       uint32_t size = 0;
+
+       size = (nb_rx_desc + RNP_RX_MAX_BURST_SIZE) *
+               sizeof(struct rnp_rxsw_entry);
+       rxq->sw_ring = rte_zmalloc_socket("rx_swring", size,
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       if (rxq->sw_ring == NULL)
+               return -ENOMEM;
+       rz = rte_eth_dma_zone_reserve(dev, "rx_ring", rxq->attr.queue_id,
+                       RNP_RX_MAX_RING_SZ, RNP_BD_RING_ALIGN, socket_id);
+       if (rz == NULL) {
+               rte_free(rxq->sw_ring);
+               rxq->sw_ring = NULL;
+               return -ENOMEM;
+       }
+       memset(rz->addr, 0, RNP_RX_MAX_RING_SZ);
+       rxq->rx_bdr = (struct rnp_rx_desc *)rz->addr;
+       rxq->ring_phys_addr = rz->iova;
+       rxq->rz = rz;
+
+       return 0;
+}
+
+static void
+rnp_rx_queue_sw_reset(struct rnp_rx_queue *rxq)
+{
+       uint32_t size = 0;
+       uint32_t idx = 0;
+
+       rxq->nb_rx_free = rxq->attr.nb_desc - 1;
+       rxq->rx_tail = 0;
+
+       size = rxq->attr.nb_desc + RNP_RX_MAX_BURST_SIZE;
+       for (idx = 0; idx < size * sizeof(struct rnp_rx_desc); idx++)
+               ((volatile char *)rxq->rx_bdr)[idx] = 0;
+}
+
+
+int rnp_rx_queue_setup(struct rte_eth_dev *eth_dev,
+                      uint16_t qidx,
+                      uint16_t nb_rx_desc,
+                      unsigned int socket_id,
+                      const struct rte_eth_rxconf *rx_conf,
+                      struct rte_mempool *mb_pool)
+{
+       struct rnp_eth_port *port = RNP_DEV_TO_PORT(eth_dev);
+       struct rte_eth_dev_data *data = eth_dev->data;
+       struct rnp_hw *hw = port->hw;
+       struct rnp_rx_queue *rxq = NULL;
+       uint64_t offloads;
+       int err = 0;
+
+       RNP_PMD_LOG(INFO, "RXQ[%d] setup nb-desc %d\n", qidx, nb_rx_desc);
+       offloads = rx_conf->offloads | data->dev_conf.rxmode.offloads;
+       if (rte_is_power_of_2(nb_rx_desc) == 0) {
+               RNP_PMD_ERR("Rxq Desc Num Must power of 2\n");
+               return -EINVAL;
+       }
+       if (nb_rx_desc > RNP_MAX_BD_COUNT)
+               return -EINVAL;
+       /* check whether queue has been created if so release it */
+       if (qidx < data->nb_rx_queues &&
+                       data->rx_queues[qidx] != NULL) {
+               rnp_rx_queue_release(data->rx_queues[qidx]);
+               data->rx_queues[qidx] = NULL;
+       }
+       rxq = rte_zmalloc_socket("rnp_rxq", sizeof(struct rnp_rx_queue),
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       if (rxq == NULL) {
+               RNP_PMD_ERR("Failed to allocate rx ring memory");
+               return -ENOMEM;
+       }
+       rxq->rx_offloads = offloads;
+       /* queue hw info */
+       rxq->attr.index = rnp_get_dma_ring_index(port, qidx);
+       rxq->attr.nb_desc_mask = nb_rx_desc - 1;
+       rxq->attr.nb_desc = nb_rx_desc;
+       rxq->attr.queue_id = qidx;
+       /* queue map to port hw info */
+       rxq->attr.vf_num = hw->mbx.vf_num;
+       rxq->attr.sriov_st = hw->mbx.sriov_st;
+       rxq->attr.lane_id = port->attr.nr_lane;
+       rxq->attr.port_id = data->port_id;
+#define RNP_RXQ_BD_TIMEOUT   (5000000)
+       rxq->nodesc_tm_thresh = RNP_RXQ_BD_TIMEOUT;
+       rxq->rx_buf_len = (uint16_t)(rte_pktmbuf_data_room_size(mb_pool) -
+                       RTE_PKTMBUF_HEADROOM);
+       rxq->mb_pool = mb_pool;
+       err = rnp_alloc_rxbdr(eth_dev, rxq, nb_rx_desc, socket_id);
+       if (err)
+               goto fail;
+       RNP_PMD_LOG(INFO, "PF[%d] dev:[%d] hw-lane[%d] rx_qid[%d] "
+                       "hw_ridx %d socket %d\n",
+                       hw->mbx.pf_num, rxq->attr.port_id,
+                       rxq->attr.lane_id, qidx,
+                       rxq->attr.index, socket_id);
+       rxq->rx_free_thresh = (rx_conf->rx_free_thresh) ?
+               rx_conf->rx_free_thresh : RNP_DEFAULT_RX_FREE_THRESH;
+       rxq->pthresh = (rx_conf->rx_thresh.pthresh) ?
+               rx_conf->rx_thresh.pthresh : RNP_RX_DESC_FETCH_TH;
+       rxq->pburst = (rx_conf->rx_thresh.hthresh) ?
+               rx_conf->rx_thresh.hthresh : RNP_RX_DESC_FETCH_BURST;
+       rnp_setup_rxbdr(hw, rxq);
+       if (rxq->rx_tail) {
+               err = rnp_rx_queue_reset(port, rxq);
+               if (err) {
+                       RNP_PMD_ERR("PF[%d] dev:[%d] lane[%d] rx_qid[%d] "
+                                   "hw_ridx[%d] bdr setup failed",
+                                   hw->mbx.pf_num, rxq->attr.port_id,
+                                   rxq->attr.lane_id, qidx, rxq->attr.index);
+                       goto rxbd_setup_failed;
+               }
+       }
+       rnp_rx_queue_sw_reset(rxq);
+       data->rx_queues[qidx] = rxq;
+
+       return 0;
+rxbd_setup_failed:
+       if (rxq->rz)
+               rte_memzone_free(rxq->rz);
+fail:
+       rte_free(rxq);
+
+       return err;
+}
+
+static void rnp_tx_queue_release_mbuf(struct rnp_tx_queue *txq)
+{
+       uint16_t i;
+
+       if (!txq)
+               return;
+       if (txq->sw_ring) {
+               for (i = 0; i < txq->attr.nb_desc; i++) {
+                       if (txq->sw_ring[i].mbuf) {
+                               rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
+                               txq->sw_ring[i].mbuf = NULL;
+                       }
+               }
+       }
+}
+
+static void rnp_tx_queue_release(void *_txq)
+{
+       struct rnp_tx_queue *txq = (struct rnp_tx_queue *)_txq;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (txq) {
+               rnp_tx_queue_release_mbuf(txq);
+
+               if (txq->rz)
+                       rte_memzone_free(txq->rz);
+               if (txq->sw_ring)
+                       rte_free(txq->sw_ring);
+               rte_free(txq);
+       }
+}
+
+void
+rnp_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+       rnp_rx_queue_release(dev->data->rx_queues[qid]);
+}
+
+void
+rnp_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+       rnp_tx_queue_release(dev->data->tx_queues[qid]);
+}
+
+static int rnp_alloc_txbdr(struct rte_eth_dev *dev,
+                          struct rnp_tx_queue *txq,
+                          uint16_t nb_desc, int socket_id)
+{
+       const struct rte_memzone *rz = NULL;
+       int size;
+
+       size = nb_desc * sizeof(struct rnp_txsw_entry);
+       txq->sw_ring = rte_zmalloc_socket("tx_swq", size,
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       if (txq->sw_ring == NULL)
+               return -ENOMEM;
+
+       rz = rte_eth_dma_zone_reserve(dev, "tx_ring", txq->attr.queue_id,
+                       RNP_TX_MAX_RING_SZ, RNP_BD_RING_ALIGN, socket_id);
+       if (rz == NULL) {
+               rte_free(txq->sw_ring);
+               txq->sw_ring = NULL;
+               return -ENOMEM;
+       }
+       memset(rz->addr, 0, RNP_TX_MAX_RING_SZ);
+       txq->ring_phys_addr = rz->iova;
+       txq->tx_bdr = rz->addr;
+       txq->rz = rz;
+
+       return 0;
+}
+
+static void
+rnp_tx_queue_sw_reset(struct rnp_tx_queue *txq)
+{
+       struct rnp_txsw_entry *sw_ring = txq->sw_ring;
+       uint32_t idx = 0, prev = 0;
+       uint32_t size = 0;
+
+       prev = (uint16_t)(txq->attr.nb_desc - 1);
+       for (idx = 0; idx < txq->attr.nb_desc; idx++) {
+               sw_ring[idx].mbuf = NULL;
+               sw_ring[idx].last_id = idx;
+               sw_ring[prev].next_id = idx;
+               prev = idx;
+       }
+       txq->nb_tx_free = txq->attr.nb_desc - 1;
+       txq->tx_next_dd = txq->tx_rs_thresh - 1;
+       txq->tx_next_rs = txq->tx_rs_thresh - 1;
+
+       size = (txq->attr.nb_desc + RNP_TX_MAX_BURST_SIZE);
+       for (idx = 0; idx < size * sizeof(struct rnp_tx_desc); idx++)
+               ((volatile char *)txq->tx_bdr)[idx] = 0;
+}
+
+int
+rnp_tx_queue_setup(struct rte_eth_dev *dev,
+                  uint16_t qidx, uint16_t nb_desc,
+                  unsigned int socket_id,
+                  const struct rte_eth_txconf *tx_conf)
+{
+       struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+       struct rte_eth_dev_data *data = dev->data;
+       struct rnp_hw *hw = port->hw;
+       struct rnp_tx_queue *txq;
+       uint64_t offloads = 0;
+       int err = 0;
+
+       PMD_INIT_FUNC_TRACE();
+       offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
+       RNP_PMD_INFO("TXQ[%d] setup nb-desc %d\n", qidx, nb_desc);
+       if (rte_is_power_of_2(nb_desc) == 0) {
+               RNP_PMD_ERR("txq Desc num must power of 2\n");
+               return -EINVAL;
+       }
+       if (nb_desc > RNP_MAX_BD_COUNT)
+               return -EINVAL;
+       /* check whether queue Has been create if so release it */
+       if (qidx < data->nb_tx_queues && data->tx_queues[qidx]) {
+               rnp_tx_queue_release(data->tx_queues[qidx]);
+               data->tx_queues[qidx] = NULL;
+       }
+       txq = rte_zmalloc_socket("rnp_txq", sizeof(struct rnp_tx_queue),
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       if (!txq) {
+               RNP_PMD_ERR("Failed to allocate TX ring memory");
+               return -ENOMEM;
+       }
+       txq->tx_rs_thresh = tx_conf->tx_rs_thresh ?
+               tx_conf->tx_rs_thresh : RNP_DEFAULT_TX_RS_THRESH;
+       txq->tx_free_thresh = tx_conf->tx_free_thresh ?
+               tx_conf->tx_free_thresh : RNP_DEFAULT_TX_FREE_THRESH;
+       if (txq->tx_rs_thresh > txq->tx_free_thresh) {
+               RNP_PMD_ERR("tx_rs_thresh must be less than or "
+                            "equal to tx_free_thresh. (tx_free_thresh=%u"
+                            " tx_rs_thresh=%u port=%d queue=%d)",
+                            (unsigned int)tx_conf->tx_free_thresh,
+                            (unsigned int)tx_conf->tx_rs_thresh,
+                            (int)data->port_id,
+                            (int)qidx);
+               err = -EINVAL;
+               goto txbd_setup_failed;
+       }
+       if (txq->tx_rs_thresh + txq->tx_free_thresh >= nb_desc) {
+               RNP_PMD_ERR("tx_rs_thresh + tx_free_thresh >= nb_desc"
+                               "%d + %d >= %d", txq->tx_rs_thresh,
+                               txq->tx_free_thresh, nb_desc);
+               err = -EINVAL;
+               goto txbd_setup_failed;
+       }
+       txq->pthresh = (tx_conf->tx_thresh.pthresh) ?
+               tx_conf->tx_thresh.pthresh : RNP_TX_DESC_FETCH_TH;
+       txq->pburst = (tx_conf->tx_thresh.hthresh) ?
+               tx_conf->tx_thresh.hthresh : RNP_TX_DESC_FETCH_BURST;
+       txq->free_mbufs = rte_zmalloc_socket("txq->free_mbufs",
+                       sizeof(struct rte_mbuf *) * txq->tx_rs_thresh,
+                       RTE_CACHE_LINE_SIZE, socket_id);
+       txq->attr.index = rnp_get_dma_ring_index(port, qidx);
+       txq->attr.lane_id = port->attr.nr_lane;
+       txq->attr.port_id = dev->data->port_id;
+       txq->attr.nb_desc_mask = nb_desc - 1;
+       txq->attr.vf_num = hw->mbx.vf_num;
+       txq->attr.nb_desc = nb_desc;
+       txq->attr.queue_id = qidx;
+
+       err = rnp_alloc_txbdr(dev, txq, nb_desc, socket_id);
+       if (err)
+               goto txbd_setup_failed;
+       rnp_setup_txbdr(hw, txq);
+       if (txq->tx_tail)
+               rnp_reset_hw_txq_op(hw, txq);
+       rnp_tx_queue_sw_reset(txq);
+       RNP_PMD_LOG(INFO, "PF[%d] dev:[%d] hw-lane[%d] txq queue_id[%d] "
+                       "dma_idx %d socket %d\n",
+                       hw->mbx.pf_num, txq->attr.port_id,
+                       txq->attr.lane_id, qidx,
+                       txq->attr.index, socket_id);
+       if (qidx < dev->data->nb_tx_queues)
+               data->tx_queues[qidx] = txq;
+       port->tx_queues[qidx] = txq;
+
+       txq->tx_deferred_start = tx_conf->tx_deferred_start;
+       txq->tx_offloads = offloads;
+
+       return 0;
+txbd_setup_failed:
+
+       rte_free(txq);
+
+       return err;
+}
diff --git a/drivers/net/rnp/rnp_rxtx.h b/drivers/net/rnp/rnp_rxtx.h
new file mode 100644
index 0000000..3ea977c
--- /dev/null
+++ b/drivers/net/rnp/rnp_rxtx.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2023 Mucse IC Design Ltd.
+ */
+
+#ifndef _RNP_RXTX_H_
+#define _RNP_RXTX_H_
+
+#include "rnp.h"
+#include "base/rnp_bdq_if.h"
+
+#define RNP_RX_MAX_BURST_SIZE  (32)
+#define RNP_TX_MAX_BURST_SIZE  (32)
+#define RNP_BD_RING_ALIGN      (128)
+#define RNP_MAX_RING_DESC      (4096)
+#define RNP_RX_MAX_RING_SZ     \
+       ((RNP_MAX_RING_DESC + \
+         RNP_RX_MAX_BURST_SIZE) * \
+        sizeof(struct rnp_rx_desc))
+#define RNP_TX_MAX_RING_SZ     \
+       ((RNP_MAX_RING_DESC + \
+         RNP_TX_MAX_BURST_SIZE) * \
+        sizeof(struct rnp_tx_desc))
+
+#define RNP_RX_DESC_FETCH_TH           (96) /* dma fetch desC threshold */
+#define RNP_RX_DESC_FETCH_BURST                (32) /* */
+#define RNP_TX_DESC_FETCH_TH           (64) /* dma fetch desc threshold */
+#define RNP_TX_DESC_FETCH_BURST                (32) /* 
max-num_descs_peer_read*/
+
+#define RNP_DEFAULT_TX_FREE_THRESH   (32)
+#define RNP_DEFAULT_TX_RS_THRESH     (32)
+#define RNP_DEFAULT_RX_FREE_THRESH   (32)
+
+/* rx queue info */
+struct rnp_queue_attr {
+       uint64_t sriov_st; /* enable sriov info */
+       uint16_t vf_num; /* ring belong to which vf */
+
+       uint16_t queue_id; /* sw queue index*/
+       uint16_t index; /* hw ring index */
+       uint16_t lane_id; /* ring belong to which physical Lane */
+       uint16_t nb_desc; /* max bds */
+       uint16_t nb_desc_mask; /* mask of bds */
+       uint16_t port_id; /* dpdk manage port sequence id */
+};
+
+struct rnp_rxsw_entry {
+       struct rte_mbuf *mbuf;
+};
+
+struct rnp_rx_queue {
+       struct rte_mempool *mb_pool; /* mbuf pool to populate rx ring. */
+       const struct rte_memzone *rz; /* rx hw ring base alloc memzone */
+       uint64_t ring_phys_addr; /* rx hw ring physical addr */
+       volatile struct rnp_rx_desc *rx_bdr; /* rx hw ring rirtual Addr */
+       volatile struct rnp_rx_desc zero_desc;
+       struct rnp_rxsw_entry *sw_ring; /* rx software ring addr */
+       volatile void *rx_tailreg; /* hw desc tail register */
+       volatile void *rx_headreg; /* hw desc head register*/
+       struct rnp_queue_attr attr;
+
+       uint16_t rx_buf_len; /* mempool mbuf buf len */
+       uint16_t nb_rx_free; /* number available use desc */
+       uint16_t rx_free_thresh; /* rx free desc desource thresh */
+       uint16_t rx_tail;
+
+       uint32_t nodesc_tm_thresh; /* rx queue no desc timeout thresh */
+       uint8_t rx_deferred_start; /* do not start queue with dev_start(). */
+       uint8_t pthresh; /* rx desc prefetch threshold */
+       uint8_t pburst; /* rx desc prefetch burst */
+
+       uint64_t rx_offloads; /* user set hw offload features */
+       struct rte_mbuf **free_mbufs; /* rx bulk alloc reserve of free mbufs */
+};
+
+struct rnp_txsw_entry {
+       struct rte_mbuf *mbuf;  /* sync with tx desc dma physical addr */
+       uint16_t next_id;       /* next entry resource used */
+       uint16_t last_id;       /* last entry resource used */
+};
+
+struct rnp_tx_desc;
+struct rnp_tx_queue {
+       const struct rte_memzone *rz;
+       uint64_t ring_phys_addr; /* tx dma ring physical addr */
+       volatile struct rnp_tx_desc *tx_bdr; /* tx dma ring virtual addr */
+       struct rnp_txsw_entry *sw_ring; /* tx software ring addr */
+       volatile void *tx_tailreg; /* hw desc tail register */
+       volatile void *tx_headreg; /* hw desc head register*/
+       struct rnp_queue_attr attr;
+
+       uint16_t nb_tx_free; /* avail desc to set pkts */
+       uint16_t nb_tx_used;
+       uint16_t tx_tail;
+
+       uint16_t tx_next_dd; /* next to scan writeback dd bit */
+       uint16_t tx_rs_thresh; /* number of interval set rs bit */
+       uint16_t tx_next_rs; /* index of next time to set rs bit*/
+       uint16_t tx_free_thresh; /* thresh to free tx desc resource */
+
+       uint8_t tx_deferred_start; /*< Do not start queue with dev_start(). */
+       uint8_t pthresh; /* rx desc prefetch threshold */
+       uint8_t pburst; /* rx desc burst*/
+
+       uint64_t tx_offloads; /* tx offload features */
+       struct rte_mbuf **free_mbufs; /* tx bulk free reserve of free mbufs */
+};
+
+void
+rnp_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
+void
+rnp_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
+int rnp_rx_queue_setup(struct rte_eth_dev *eth_dev,
+                      uint16_t qidx,
+                      uint16_t nb_rx_desc,
+                      unsigned int socket_id,
+                      const struct rte_eth_rxconf *rx_conf,
+                      struct rte_mempool *mb_pool);
+int rnp_tx_queue_setup(struct rte_eth_dev *dev,
+                      uint16_t qidx, uint16_t nb_desc,
+                      unsigned int socket_id,
+                      const struct rte_eth_txconf *tx_conf);
+
+#endif /* _RNP_RXTX_H_ */
-- 
1.8.3.1


Reply via email to