optimize queue res alloc/free process.<br /> <br />Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn> <br />---<br /> drivers/net/zxdh/zxdh_common.c     |  27 ++--<br /> drivers/net/zxdh/zxdh_ethdev.c     | 200 ++++++++++++++++++++---------<br /> drivers/net/zxdh/zxdh_ethdev.h     |  14 +-<br /> drivers/net/zxdh/zxdh_ethdev_ops.c |  13 +-<br /> drivers/net/zxdh/zxdh_pci.c        |  10 --<br /> drivers/net/zxdh/zxdh_queue.c      | 123 +++++++++++-------<br /> 6 files changed, 251 insertions(+), 136 deletions(-)<br /> <br />diff --git a/drivers/net/zxdh/zxdh_common.c b/drivers/net/zxdh/zxdh_common.c<br />index 7158bd735d..6be7dbf504 100644<br />--- a/drivers/net/zxdh/zxdh_common.c<br />+++ b/drivers/net/zxdh/zxdh_common.c<br />@@ -398,27 +398,30 @@ int32_t<br /> zxdh_datach_set(struct rte_eth_dev *dev)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint16_t buff_size = (hw->queue_num + 1) * 2;<br />-    int32_t ret = 0;<br />-    uint16_t i;<br />+    uint16_t nr_vq = hw->rx_qnum + hw->tx_qnum;<br />+    uint16_t buff_size = (nr_vq % ZXDH_QUEUES_NUM_MAX + 1) * sizeof(uint16_t);<br />+    int ret = 0;<br />+    uint16_t *pdata, i;<br />  <br />     void *buff = rte_zmalloc(NULL, buff_size, 0);<br />+<br />     if (unlikely(buff == NULL)) {<br />         PMD_DRV_LOG(ERR, "Failed to allocate buff");<br />         return -ENOMEM;<br />     }<br />-    memset(buff, 0, buff_size);<br />-    uint16_t *pdata = (uint16_t *)buff;<br />-    *pdata++ = hw->queue_num;<br />  <br />-    for (i = 0; i < hw->queue_num; i++)<br />-        *(pdata + i) = hw->channel_context[i].ph_chno;<br />+    pdata = (uint16_t *)buff;<br />+    *pdata++ = nr_vq;<br />+    for (i = 0; i < hw->rx_qnum; i++)<br />+        *(pdata + i) = hw->channel_context[i * 2].ph_chno;<br />+    for (i = 0; i < hw->tx_qnum; i++)<br />+        *(pdata + hw->rx_qnum + i) = hw->channel_context[i * 2 + 1].ph_chno;<br />+    ret = zxdh_common_table_write(hw, ZXDH_COMMON_FIELD_DATACH, (void *)buff, buff_size);<br />  <br />-    ret = zxdh_common_table_write(hw, ZXDH_COMMON_FIELD_DATACH,<br />-                        (void *)buff, buff_size);<br />     if (ret != 0)<br />-        PMD_DRV_LOG(ERR, "Failed to setup data channel of common table");<br />-<br />+        PMD_DRV_LOG(ERR, "Failed to setup data channel of common table. code:%d", ret);<br />+    hw->queue_set_flag = 1;<br />     rte_free(buff);<br />+<br />     return ret;<br /> }<br />diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c<br />index 9e6f7d6340..8241c26624 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev.c<br />+++ b/drivers/net/zxdh/zxdh_ethdev.c<br />@@ -25,6 +25,9 @@ static struct zxdh_shared_data *zxdh_shared_data;<br />  <br /> #define ZXDH_INVALID_DTBQUE      0xFFFF<br /> #define ZXDH_INVALID_SLOT_IDX    0xFFFF<br />+#define ZXDH_PF_QUEUE_PAIRS_ADDR            0x5742<br />+#define ZXDH_VF_QUEUE_PAIRS_ADDR            0x5744<br />+#define ZXDH_QUEUE_POOL_ADDR                0x56A0<br />  <br /> uint16_t<br /> zxdh_vport_to_vfid(union zxdh_virport_num v)<br />@@ -89,10 +92,11 @@ zxdh_queues_unbind_intr(struct rte_eth_dev *dev)<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />     int32_t i;<br />  <br />-    for (i = 0; i < dev->data->nb_rx_queues; ++i) {<br />+    for (i = 0; i < dev->data->nb_rx_queues; ++i)<br />         ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR);<br />+<br />+    for (i = 0; i < dev->data->nb_tx_queues; ++i)<br />         ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2 + 1], ZXDH_MSI_NO_VECTOR);<br />-    }<br /> }<br />  <br />  <br />@@ -466,33 +470,30 @@ static void<br /> zxdh_dev_free_mbufs(struct rte_eth_dev *dev)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint16_t nr_vq = hw->queue_num;<br />-    uint32_t i = 0;<br />-<br />-    const char *type = NULL;<br />-    struct zxdh_virtqueue *vq = NULL;<br />-    struct rte_mbuf *buf = NULL;<br />-    int32_t queue_type = 0;<br />+    struct zxdh_virtqueue *vq;<br />+    struct rte_mbuf *buf;<br />+    int i;<br />  <br />     if (hw->vqs == NULL)<br />         return;<br />  <br />-    for (i = 0; i < nr_vq; i++) {<br />-        vq = hw->vqs[i];<br />+    for (i = 0; i < hw->rx_qnum; i++) {<br />+        vq = hw->vqs[i * 2];<br />         if (!vq)<br />             continue;<br />-<br />-        queue_type = zxdh_get_queue_type(i);<br />-        if (queue_type == ZXDH_VTNET_RQ)<br />-            type = "rxq";<br />-        else if (queue_type == ZXDH_VTNET_TQ)<br />-            type = "txq";<br />-        else<br />+        while ((buf = zxdh_queue_detach_unused(vq)) != NULL)<br />+            rte_pktmbuf_free(buf);<br />+        PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",<br />+        "rxq", i * 2);<br />+    }<br />+    for (i = 0; i < hw->tx_qnum; i++) {<br />+        vq = hw->vqs[i * 2 + 1];<br />+        if (!vq)<br />             continue;<br />-        PMD_DRV_LOG(DEBUG, "Before freeing %s[%d] used and unused buf", type, i);<br />-<br />         while ((buf = zxdh_queue_detach_unused(vq)) != NULL)<br />             rte_pktmbuf_free(buf);<br />+        PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",<br />+        "txq", i * 2 + 1);<br />     }<br /> }<br />  <br />@@ -500,10 +501,16 @@ static int32_t<br /> zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint16_t base    = (queue_type == ZXDH_VTNET_RQ) ? 0 : 1;<br />-    uint16_t i       = 0;<br />-    uint16_t j       = 0;<br />-    uint16_t done    = 0;<br />+    uint16_t base     = (queue_type == ZXDH_VTNET_RQ) ? 0 : 1;  /* txq only polls odd bits*/<br />+    uint16_t j         = 0;<br />+    uint16_t done     = 0;<br />+    uint32_t phy_vq_reg = 0;<br />+    uint16_t total_queue_num = hw->queue_pool_count * 2;<br />+    uint16_t start_qp_id = hw->queue_pool_start * 2;<br />+    uint32_t phy_vq_reg_oft = start_qp_id / 32;<br />+    uint32_t inval_bit = start_qp_id % 32;<br />+    uint32_t res_bit = (total_queue_num + inval_bit) % 32;<br />+    uint32_t vq_reg_num = (total_queue_num + inval_bit) / 32 + (res_bit ? 1 : 0);<br />     int32_t ret = 0;<br />  <br />     ret = zxdh_timedlock(hw, 1000);<br />@@ -512,23 +519,49 @@ zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type)<br />         return -1;<br />     }<br />  <br />-    /* Iterate COI table and find free channel */<br />-    for (i = ZXDH_QUEUES_BASE / 32; i < ZXDH_TOTAL_QUEUES_NUM / 32; i++) {<br />-        uint32_t addr = ZXDH_QUERES_SHARE_BASE + (i * sizeof(uint32_t));<br />+    for (phy_vq_reg = 0; phy_vq_reg < vq_reg_num; phy_vq_reg++) {<br />+        uint32_t addr = ZXDH_QUERES_SHARE_BASE +<br />+        (phy_vq_reg + phy_vq_reg_oft) * sizeof(uint32_t);<br />         uint32_t var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);<br />-<br />-        for (j = base; j < 32; j += 2) {<br />-            /* Got the available channel & update COI table */<br />-            if ((var & (1 << j)) == 0) {<br />-                var |= (1 << j);<br />-                zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />-                done = 1;<br />+        if (phy_vq_reg == 0) {<br />+            for (j = (inval_bit + base); j < 32; j += 2) {<br />+                /* Got the available channel & update COI table */<br />+                if ((var & (1 << j)) == 0) {<br />+                    var |= (1 << j);<br />+                    zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />+                    done = 1;<br />+                    break;<br />+                }<br />+            }<br />+            if (done)<br />                 break;<br />+        } else if ((phy_vq_reg == (vq_reg_num - 1)) && (res_bit != 0)) {<br />+            for (j = base; j < res_bit; j += 2) {<br />+                /* Got the available channel & update COI table */<br />+                if ((var & (1 << j)) == 0) {<br />+                    var |= (1 << j);<br />+                    zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />+                    done = 1;<br />+                    break;<br />+                }<br />             }<br />+            if (done)<br />+                break;<br />+        } else {<br />+            for (j = base; j < 32; j += 2) {<br />+                /* Got the available channel & update COI table */<br />+                if ((var & (1 << j)) == 0) {<br />+                    var |= (1 << j);<br />+                    zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />+                    done = 1;<br />+                    break;<br />+                }<br />+            }<br />+            if (done)<br />+                break;<br />         }<br />-        if (done)<br />-            break;<br />     }<br />+<br />     zxdh_release_lock(hw);<br />     /* check for no channel condition */<br />     if (done != 1) {<br />@@ -536,7 +569,7 @@ zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type)<br />         return -1;<br />     }<br />     /* reruen available channel ID */<br />-    return (i * 32) + j;<br />+    return (phy_vq_reg + phy_vq_reg_oft) * 32 + j;<br /> }<br />  <br /> static int32_t<br />@@ -741,29 +774,46 @@ zxdh_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_logic_qidx)<br /> }<br />  <br /> static int32_t<br />-zxdh_alloc_queues(struct rte_eth_dev *dev, uint16_t nr_vq)<br />+zxdh_alloc_queues(struct rte_eth_dev *dev)<br /> {<br />-    uint16_t lch;<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-<br />+    u_int16_t rxq_num = hw->rx_qnum;<br />+    u_int16_t txq_num = hw->tx_qnum;<br />+    uint16_t nr_vq = (rxq_num > txq_num) ? 2 * rxq_num : 2 * txq_num;<br />     hw->vqs = rte_zmalloc(NULL, sizeof(struct zxdh_virtqueue *) * nr_vq, 0);<br />+    uint16_t lch, i;<br />+<br />     if (!hw->vqs) {<br />-        PMD_DRV_LOG(ERR, "Failed to allocate vqs");<br />+        PMD_DRV_LOG(ERR, "Failed to allocate %d vqs", nr_vq);<br />         return -ENOMEM;<br />     }<br />-    for (lch = 0; lch < nr_vq; lch++) {<br />+    for (i = 0 ; i < rxq_num; i++) {<br />+        lch = i * 2;<br />         if (zxdh_acquire_channel(dev, lch) < 0) {<br />             PMD_DRV_LOG(ERR, "Failed to acquire the channels");<br />-            zxdh_free_queues(dev);<br />-            return -1;<br />+            goto free;<br />         }<br />         if (zxdh_init_queue(dev, lch) < 0) {<br />             PMD_DRV_LOG(ERR, "Failed to alloc virtio queue");<br />-            zxdh_free_queues(dev);<br />-            return -1;<br />+            goto free;<br />+        }<br />+    }<br />+    for (i = 0 ; i < txq_num; i++) {<br />+        lch = i * 2 + 1;<br />+        if (zxdh_acquire_channel(dev, lch) < 0) {<br />+            PMD_DRV_LOG(ERR, "Failed to acquire the channels");<br />+            goto free;<br />+        }<br />+        if (zxdh_init_queue(dev, lch) < 0) {<br />+            PMD_DRV_LOG(ERR, "Failed to alloc virtio queue");<br />+            goto free;<br />         }<br />     }<br />     return 0;<br />+<br />+free:<br />+    zxdh_free_queues(dev);<br />+    return -1;<br /> }<br />  <br /> static int<br />@@ -840,20 +890,15 @@ zxdh_dev_configure(struct rte_eth_dev *dev)<br />     const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;<br />     const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint32_t nr_vq = 0;<br />     int32_t  ret = 0;<br />  <br />-    if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {<br />-        PMD_DRV_LOG(ERR, "nb_rx_queues=%d and nb_tx_queues=%d not equal!",<br />-                     dev->data->nb_rx_queues, dev->data->nb_tx_queues);<br />-        return -EINVAL;<br />-    }<br />-    if ((dev->data->nb_rx_queues + dev->data->nb_tx_queues) >= ZXDH_QUEUES_NUM_MAX) {<br />-        PMD_DRV_LOG(ERR, "nb_rx_queues=%d + nb_tx_queues=%d must < (%d)!",<br />-                     dev->data->nb_rx_queues, dev->data->nb_tx_queues,<br />-                     ZXDH_QUEUES_NUM_MAX);<br />+    if (dev->data->nb_rx_queues > hw->max_queue_pairs ||<br />+        dev->data->nb_tx_queues > hw->max_queue_pairs) {<br />+        PMD_DRV_LOG(ERR, "nb_rx_queues=%d or nb_tx_queues=%d must < (%d)!",<br />+        dev->data->nb_rx_queues, dev->data->nb_tx_queues, hw->max_queue_pairs);<br />         return -EINVAL;<br />     }<br />+<br />     if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {<br />         PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);<br />         return -EINVAL;<br />@@ -888,9 +933,13 @@ zxdh_dev_configure(struct rte_eth_dev *dev)<br />     hw->has_tx_offload = zxdh_tx_offload_enabled(hw);<br />     hw->has_rx_offload = zxdh_rx_offload_enabled(hw);<br />  <br />-    nr_vq = dev->data->nb_rx_queues + dev->data->nb_tx_queues;<br />-    if (nr_vq == hw->queue_num)<br />+    if (dev->data->nb_rx_queues == hw->rx_qnum && <br />+            dev->data->nb_tx_queues == hw->tx_qnum) {<br />+        PMD_DRV_LOG(DEBUG, "The queue not need to change. queue_rx %d queue_tx %d",<br />+                hw->rx_qnum, hw->tx_qnum);<br />+        /*no queue changed */<br />         goto end;<br />+    }<br />  <br />     PMD_DRV_LOG(DEBUG, "queue changed need reset");<br />     /* Reset the device although not necessary at startup */<br />@@ -907,8 +956,9 @@ zxdh_dev_configure(struct rte_eth_dev *dev)<br />         zxdh_free_queues(dev);<br />     }<br />  <br />-    hw->queue_num = nr_vq;<br />-    ret = zxdh_alloc_queues(dev, nr_vq);<br />+    hw->rx_qnum = dev->data->nb_rx_queues;<br />+    hw->tx_qnum = dev->data->nb_tx_queues;<br />+    ret = zxdh_alloc_queues(dev);<br />     if (ret < 0)<br />         return ret;<br />  <br />@@ -1550,6 +1600,35 @@ zxdh_tables_init(struct rte_eth_dev *dev)<br />     return ret;<br /> }<br />  <br />+static void<br />+zxdh_queue_res_get(struct rte_eth_dev *eth_dev)<br />+{<br />+    struct zxdh_hw *hw = eth_dev->data->dev_private;<br />+    uint32_t value = 0;<br />+    uint16_t offset = 0;<br />+<br />+    if (hw->is_pf) {<br />+        hw->max_queue_pairs = *(volatile uint8_t *)(hw->bar_addr[0] +<br />+        ZXDH_PF_QUEUE_PAIRS_ADDR);<br />+        PMD_DRV_LOG(DEBUG, "is_pf max_queue_pairs is %x", hw->max_queue_pairs);<br />+    } else {<br />+        hw->max_queue_pairs = *(volatile uint8_t *)(hw->bar_addr[0] +<br />+        ZXDH_VF_QUEUE_PAIRS_ADDR + offset);<br />+        PMD_DRV_LOG(DEBUG, "is_vf max_queue_pairs is %x", hw->max_queue_pairs);<br />+    }<br />+<br />+    /*  pf/vf read queue start id and queue_max cfg */<br />+    value = *(volatile uint32_t *)(hw->bar_addr[0] + ZXDH_QUEUE_POOL_ADDR + offset * 4);<br />+    hw->queue_pool_count = value & 0x0000ffff;<br />+    hw->queue_pool_start = value >> 16;<br />+    if (hw->max_queue_pairs > ZXDH_RX_QUEUES_MAX || hw->max_queue_pairs == 0)<br />+        hw->max_queue_pairs = ZXDH_RX_QUEUES_MAX;<br />+    if (hw->queue_pool_count > ZXDH_TOTAL_QUEUES_NUM / 2 || hw->queue_pool_count == 0)<br />+        hw->queue_pool_count = ZXDH_TOTAL_QUEUES_NUM / 2;<br />+    if (hw->queue_pool_start > ZXDH_TOTAL_QUEUES_NUM / 2)<br />+        hw->queue_pool_start = 0;<br />+}<br />+<br /> static int<br /> zxdh_eth_dev_init(struct rte_eth_dev *eth_dev)<br /> {<br />@@ -1623,6 +1702,7 @@ zxdh_eth_dev_init(struct rte_eth_dev *eth_dev)<br />     if (ret)<br />         goto err_zxdh_init;<br />  <br />+    zxdh_queue_res_get(eth_dev);<br />     ret = zxdh_configure_intr(eth_dev);<br />     if (ret != 0)<br />         goto err_zxdh_init;<br />diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h<br />index 2c11efb23c..ea69ad533b 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev.h<br />+++ b/drivers/net/zxdh/zxdh_ethdev.h<br />@@ -23,8 +23,8 @@<br /> #define ZXDH_MAX_MAC_ADDRS        (ZXDH_MAX_UC_MAC_ADDRS + ZXDH_MAX_MC_MAC_ADDRS)<br />  <br /> #define ZXDH_NUM_BARS             2<br />-#define ZXDH_RX_QUEUES_MAX        128U<br />-#define ZXDH_TX_QUEUES_MAX        128U<br />+#define ZXDH_RX_QUEUES_MAX        127U<br />+#define ZXDH_TX_QUEUES_MAX        127U<br /> #define ZXDH_MIN_RX_BUFSIZE       64<br /> #define ZXDH_MAX_RX_PKTLEN        14000U<br /> #define ZXDH_QUEUE_DEPTH          1024<br />@@ -71,16 +71,17 @@ struct zxdh_hw {<br />     uint64_t bar_addr[ZXDH_NUM_BARS];<br />     uint64_t host_features;<br />     uint64_t guest_features;<br />-    uint32_t max_queue_pairs;<br />     uint32_t speed;<br />     uint32_t speed_mode;<br />     uint32_t notify_off_multiplier;<br />     union zxdh_virport_num vport;<br />+    uint16_t max_queue_pairs;<br />     uint16_t pcie_id;<br />     uint16_t device_id;<br />     uint16_t port_id;<br />     uint16_t vfid;<br />-    uint16_t queue_num;<br />+    uint16_t rx_qnum;<br />+    uint16_t tx_qnum;<br />     uint16_t mc_num;<br />     uint16_t uc_num;<br />  <br />@@ -107,6 +108,11 @@ struct zxdh_hw {<br />     uint8_t rss_enable;<br />     uint8_t rss_init;<br />     uint16_t slot_id;<br />+<br />+    uint8_t queue_set_flag;<br />+    uint16_t queue_pool_count;<br />+    uint16_t queue_pool_start;<br />+    uint8_t rsv[3];<br /> };<br />  <br /> struct zxdh_dtb_shared_data {<br />diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c<br />index 50a585edad..7ebb231362 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev_ops.c<br />+++ b/drivers/net/zxdh/zxdh_ethdev_ops.c<br />@@ -936,14 +936,15 @@ zxdh_dev_rss_reta_update(struct rte_eth_dev *dev,<br /> static uint16_t<br /> zxdh_hw_qid_to_logic_qid(struct rte_eth_dev *dev, uint16_t qid)<br /> {<br />-    struct zxdh_hw *hw = (struct zxdh_hw *)dev->data->dev_private;<br />-    uint16_t rx_queues = dev->data->nb_rx_queues;<br />+    struct zxdh_hw *priv = (struct zxdh_hw *)dev->data->dev_private;<br />     uint16_t i;<br />  <br />-    for (i = 0; i < rx_queues; i++) {<br />-        if (qid == hw->channel_context[i * 2].ph_chno)<br />-            return i;<br />+    for (i = 0; i < priv->max_queue_pairs * 2 ; i++) {<br />+        if (priv->channel_context[i].valid)<br />+            if (qid == priv->channel_context[i].ph_chno)<br />+                return i;<br />     }<br />+<br />     return ZXDH_INVALID_LOGIC_QID;<br /> }<br />  <br />@@ -1001,7 +1002,7 @@ zxdh_dev_rss_reta_query(struct rte_eth_dev *dev,<br />                 reta_table->reta[i], qid_logic);<br />             return -EINVAL;<br />         }<br />-        reta_conf[idx].reta[i % RTE_ETH_RETA_GROUP_SIZE] = qid_logic;<br />+        reta_conf[idx].reta[i % RTE_ETH_RETA_GROUP_SIZE] = qid_logic >> 1;<br />     }<br />     return 0;<br /> }<br />diff --git a/drivers/net/zxdh/zxdh_pci.c b/drivers/net/zxdh/zxdh_pci.c<br />index 959b1b8cff..3d1a3ff0dd 100644<br />--- a/drivers/net/zxdh/zxdh_pci.c<br />+++ b/drivers/net/zxdh/zxdh_pci.c<br />@@ -396,7 +396,6 @@ zxdh_get_pci_dev_config(struct zxdh_hw *hw)<br /> {<br />     uint64_t guest_features = 0;<br />     uint64_t nego_features = 0;<br />-    uint32_t max_queue_pairs = 0;<br />  <br />     hw->host_features = zxdh_pci_get_features(hw);<br />  <br />@@ -411,15 +410,6 @@ zxdh_get_pci_dev_config(struct zxdh_hw *hw)<br />     } else {<br />         rte_eth_random_addr(&hw->mac_addr[0]);<br />     }<br />-<br />-    zxdh_pci_read_dev_config(hw, offsetof(struct zxdh_net_config, max_virtqueue_pairs),<br />-            &max_queue_pairs, sizeof(max_queue_pairs));<br />-<br />-    if (max_queue_pairs == 0)<br />-        hw->max_queue_pairs = ZXDH_RX_QUEUES_MAX;<br />-    else<br />-        hw->max_queue_pairs = RTE_MIN(ZXDH_RX_QUEUES_MAX, max_queue_pairs);<br />-    PMD_DRV_LOG(DEBUG, "set max queue pairs %d", hw->max_queue_pairs);<br /> }<br />  <br /> enum zxdh_msix_status zxdh_pci_msix_detect(struct rte_pci_device *dev)<br />diff --git a/drivers/net/zxdh/zxdh_queue.c b/drivers/net/zxdh/zxdh_queue.c<br />index 8c8f2605f6..f4a4f0ad4d 100644<br />--- a/drivers/net/zxdh/zxdh_queue.c<br />+++ b/drivers/net/zxdh/zxdh_queue.c<br />@@ -36,44 +36,75 @@ zxdh_queue_detach_unused(struct zxdh_virtqueue *vq)<br />     return NULL;<br /> }<br />  <br />+static void<br />+zxdh_clear_channel(struct rte_eth_dev *dev, uint16_t lch)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    uint16_t pch;<br />+    uint32_t var, addr, widx, bidx;<br />+<br />+    if (hw->channel_context[lch].valid == 0)<br />+        return;<br />+    /* get coi table offset and index */<br />+    pch  = hw->channel_context[lch].ph_chno;<br />+    widx = pch / 32;<br />+    bidx = pch % 32;<br />+    addr = ZXDH_QUERES_SHARE_BASE + (widx * sizeof(uint32_t));<br />+    var  = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);<br />+    var &= ~(1 << bidx);<br />+    zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />+    hw->channel_context[lch].valid = 0;<br />+    hw->channel_context[lch].ph_chno = 0;<br />+    PMD_DRV_LOG(DEBUG, " phyque %d release end ", pch);<br />+}<br />+<br /> static int32_t<br /> zxdh_release_channel(struct rte_eth_dev *dev)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint16_t nr_vq = hw->queue_num;<br />-    uint32_t var  = 0;<br />-    uint32_t addr = 0;<br />-    uint32_t widx = 0;<br />-    uint32_t bidx = 0;<br />-    uint16_t pch  = 0;<br />-    uint16_t lch  = 0;<br />+    u_int16_t rxq_num = hw->rx_qnum;<br />+    u_int16_t txq_num = hw->tx_qnum;<br />+    uint16_t lch, i;<br />     int32_t ret = 0;<br />  <br />+    if (hw->queue_set_flag == 1) {<br />+        for (i = 0; i < rxq_num; i++) {<br />+            lch = i * 2;<br />+            PMD_DRV_LOG(DEBUG, "free success!");<br />+            if (hw->channel_context[lch].valid == 0)<br />+                continue;<br />+            PMD_DRV_LOG(DEBUG, "phyque %d  no need to release backend do it",<br />+                        hw->channel_context[lch].ph_chno);<br />+            hw->channel_context[lch].valid = 0;<br />+            hw->channel_context[lch].ph_chno = 0;<br />+        }<br />+        for (i = 0; i < txq_num; i++) {<br />+            lch = i * 2 + 1;<br />+            PMD_DRV_LOG(DEBUG, "free success!");<br />+            if (hw->channel_context[lch].valid == 0)<br />+                continue;<br />+            PMD_DRV_LOG(DEBUG, "phyque %d  no need to release backend do it",<br />+                        hw->channel_context[lch].ph_chno);<br />+            hw->channel_context[lch].valid = 0;<br />+            hw->channel_context[lch].ph_chno = 0;<br />+        }<br />+        hw->queue_set_flag = 0;<br />+        return 0;<br />+    }<br />     ret = zxdh_timedlock(hw, 1000);<br />     if (ret) {<br />         PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout");<br />         return -1;<br />     }<br />  <br />-    for (lch = 0; lch < nr_vq; lch++) {<br />-        if (hw->channel_context[lch].valid == 0) {<br />-            PMD_DRV_LOG(DEBUG, "Logic channel %d does not need to release", lch);<br />-            continue;<br />-        }<br />-<br />-        pch  = hw->channel_context[lch].ph_chno;<br />-        widx = pch / 32;<br />-        bidx = pch % 32;<br />-<br />-        addr = ZXDH_QUERES_SHARE_BASE + (widx * sizeof(uint32_t));<br />-        var  = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);<br />-        var &= ~(1 << bidx);<br />-        zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);<br />-<br />-        hw->channel_context[lch].valid = 0;<br />-        hw->channel_context[lch].ph_chno = 0;<br />+    for (i = 0 ; i < rxq_num ; i++) {<br />+        lch = i * 2;<br />+        zxdh_clear_channel(dev, lch);<br />+    }<br />+    for (i = 0; i < txq_num ; i++) {<br />+        lch = i * 2 + 1;<br />+        zxdh_clear_channel(dev, lch);<br />     }<br />-<br />     zxdh_release_lock(hw);<br />  <br />     return 0;<br />@@ -92,37 +123,41 @@ int32_t<br /> zxdh_free_queues(struct rte_eth_dev *dev)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />-    uint16_t nr_vq = hw->queue_num;<br />     struct zxdh_virtqueue *vq = NULL;<br />-    int32_t queue_type = 0;<br />+    u_int16_t rxq_num = hw->rx_qnum;<br />+    u_int16_t txq_num = hw->tx_qnum;<br />     uint16_t i = 0;<br />  <br />     if (hw->vqs == NULL)<br />         return 0;<br />  <br />-    if (zxdh_release_channel(dev) < 0) {<br />-        PMD_DRV_LOG(ERR, "Failed to clear coi table");<br />-        return -1;<br />-    }<br />-<br />-    for (i = 0; i < nr_vq; i++) {<br />-        vq = hw->vqs[i];<br />+    for (i = 0; i < rxq_num; i++) {<br />+        vq = hw->vqs[i * 2];<br />         if (vq == NULL)<br />             continue;<br />  <br />         ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq);<br />-        queue_type = zxdh_get_queue_type(i);<br />-        if (queue_type == ZXDH_VTNET_RQ) {<br />-            rte_free(vq->sw_ring);<br />-            rte_memzone_free(vq->rxq.mz);<br />-        } else if (queue_type == ZXDH_VTNET_TQ) {<br />-            rte_memzone_free(vq->txq.mz);<br />-            rte_memzone_free(vq->txq.zxdh_net_hdr_mz);<br />-        }<br />+        rte_memzone_free(vq->rxq.mz);<br />+        rte_free(vq);<br />+        hw->vqs[i * 2] = NULL;<br />+        PMD_MSG_LOG(DEBUG, "Release to queue %d success!", i * 2);<br />+    }<br />+    for (i = 0; i < txq_num; i++) {<br />+        vq = hw->vqs[i * 2 + 1];<br />+        if (vq == NULL)<br />+            continue;<br />  <br />+        ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq);<br />+        rte_memzone_free(vq->txq.mz);<br />+        rte_memzone_free(vq->txq.zxdh_net_hdr_mz);<br />         rte_free(vq);<br />-        hw->vqs[i] = NULL;<br />-        PMD_DRV_LOG(DEBUG, "Release to queue %d success!", i);<br />+        hw->vqs[i * 2 + 1] = NULL;<br />+        PMD_DRV_LOG(DEBUG, "Release to queue %d success!", i * 2 + 1);<br />+    }<br />+<br />+    if (zxdh_release_channel(dev) < 0) {<br />+        PMD_DRV_LOG(ERR, "Failed to clear coi table");<br />+        return -1;<br />     }<br />  <br />     rte_free(hw->vqs);<br />--  <br />2.27.0<br />