The hardware tracks a single queue depth, which the root context takes
from queue 0. A queue configured with a different depth used to be
silently coerced to the first queue's depth; reject it with -EINVAL
instead, since the application sized its mempool for the requested
depth.

Keep the expected depth in the per-port state, reset it in
dev_configure() and dev_stop(), and validate in dev_start() that every
configured queue is present and shares queue 0's depth.

Reset the rx/tx queue states in dev_stop, including the tx queue status
used by the Tx path, so the queue state reflects the stopped device
before the next start.

Signed-off-by: Jiacheng Ye <[email protected]>
---
 drivers/net/hinic3/hinic3_ethdev.c | 63 ++++++++++++++++++++++++------
 drivers/net/hinic3/hinic3_ethdev.h |  5 +++
 drivers/net/hinic3/hinic3_nic_io.c | 27 +++++++++++++
 3 files changed, 82 insertions(+), 13 deletions(-)

diff --git a/drivers/net/hinic3/hinic3_ethdev.c 
b/drivers/net/hinic3/hinic3_ethdev.c
index 47740d56d9..e939b33fd3 100644
--- a/drivers/net/hinic3/hinic3_ethdev.c
+++ b/drivers/net/hinic3/hinic3_ethdev.c
@@ -318,8 +318,6 @@ hinic3_xstats_calc_num(struct hinic3_nic_dev *nic_dev)
        }
 }
 
-#define HINIC3_MAX_QUEUE_DEPTH 16384
-#define HINIC3_MIN_QUEUE_DEPTH 128
 #define HINIC3_TXD_ALIGN       1
 #define HINIC3_RXD_ALIGN       1
 
@@ -739,6 +737,8 @@ hinic3_dev_configure(struct rte_eth_dev *dev)
 
        nic_dev->num_sqs = dev->data->nb_tx_queues;
        nic_dev->num_rqs = dev->data->nb_rx_queues;
+       nic_dev->rxq_depth = 0;
+       nic_dev->txq_depth = 0;
 
        nic_dev->mtu_size =
                
(uint16_t)HINIC3_PKTLEN_TO_MTU(HINIC3_MAX_RX_PKT_LEN(dev->data->dev_conf.rxmode));
@@ -1116,16 +1116,8 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t 
qid, uint16_t nb_desc,
 
        nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
 
-       /* Queue depth must be equal to queue 0 */
-       if (qid != 0 && nb_desc != nic_dev->rxqs[0]->q_depth) {
-               PMD_DRV_LOG(WARNING, "rxq%u depth:%u is not equal to queue0 
depth:%u.",
-                           qid, nb_desc, nic_dev->rxqs[0]->q_depth);
-               nb_desc = nic_dev->rxqs[0]->q_depth;
-       }
-
        /* Queue depth must be power of 2, otherwise will be aligned up. */
-       rq_depth = (nb_desc & (nb_desc - 1))
-                       ? ((uint16_t)(1U << (rte_log2_u32(nb_desc) + 1))) : 
nb_desc;
+       rq_depth = (uint16_t)rte_align32pow2(nb_desc);
 
        /*
         * Validate number of receive descriptors.
@@ -1142,6 +1134,21 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t 
qid, uint16_t nb_desc,
                return -EINVAL;
        }
 
+       /*
+        * The hardware tracks a single queue depth. Keep the value chosen by
+        * the first queue of this configuration and compare against it, so a
+        * runtime reconfiguration with a different depth is not rejected by
+        * queues that still hold the previous depth.
+        */
+       if (nic_dev->rxq_depth == 0)
+               nic_dev->rxq_depth = rq_depth;
+       else if (nic_dev->rxq_depth != rq_depth) {
+               PMD_DRV_LOG(ERR,
+                           "rxq%u depth:%u is not equal to the port depth:%u.",
+                           qid, rq_depth, nic_dev->rxq_depth);
+               return -EINVAL;
+       }
+
        /*
         * The RX descriptor ring will be cleaned after rxq->rx_free_thresh
         * descriptors are used or if the number of descriptors required
@@ -1351,8 +1358,7 @@ hinic3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t 
qid, uint16_t nb_desc,
        hwdev = nic_dev->hwdev;
 
        /* Queue depth must be power of 2, otherwise will be aligned up. */
-       sq_depth = (nb_desc & (nb_desc - 1))
-                               ? ((uint16_t)(1U << (rte_log2_u32(nb_desc) + 
1))) : nb_desc;
+       sq_depth = (uint16_t)rte_align32pow2(nb_desc);
 
        /*
         * Validate number of transmit descriptors.
@@ -1369,6 +1375,21 @@ hinic3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t 
qid, uint16_t nb_desc,
                return -EINVAL;
        }
 
+       /*
+        * The hardware tracks a single queue depth. Keep the value chosen by
+        * the first queue of this configuration and compare against it, so a
+        * runtime reconfiguration with a different depth is not rejected by
+        * queues that still hold the previous depth.
+        */
+       if (nic_dev->txq_depth == 0)
+               nic_dev->txq_depth = sq_depth;
+       else if (nic_dev->txq_depth != sq_depth) {
+               PMD_DRV_LOG(ERR,
+                           "txq%u depth:%u is not equal to the port depth:%u.",
+                           qid, sq_depth, nic_dev->txq_depth);
+               return -EINVAL;
+       }
+
        /*
         * The TX descriptor ring will be cleaned after txq->tx_free_thresh
         * descriptors are used or if the number of descriptors required
@@ -2234,6 +2255,7 @@ hinic3_dev_stop(struct rte_eth_dev *dev)
 {
        struct hinic3_nic_dev *nic_dev;
        struct rte_eth_link link;
+       uint16_t i;
        int err;
 
        nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
@@ -2285,6 +2307,21 @@ hinic3_dev_stop(struct rte_eth_dev *dev)
 
        /* Free mempool. */
        hinic3_copy_mempool_uninit(nic_dev);
+
+       /* A stopped device starts a new queue configuration. */
+       nic_dev->rxq_depth = 0;
+       nic_dev->txq_depth = 0;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++)
+               dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               struct hinic3_txq *txq = dev->data->tx_queues[i];
+
+               if (txq != NULL)
+                       HINIC3_SET_TXQ_STOPPED(txq);
+               dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+       }
+
        return 0;
 }
 
diff --git a/drivers/net/hinic3/hinic3_ethdev.h 
b/drivers/net/hinic3/hinic3_ethdev.h
index 0763665885..eff0bca29e 100644
--- a/drivers/net/hinic3/hinic3_ethdev.h
+++ b/drivers/net/hinic3/hinic3_ethdev.h
@@ -15,6 +15,9 @@
 
 #define HINIC3_PMD_DRV_VERSION "B106"
 
+#define HINIC3_MAX_QUEUE_DEPTH         16384
+#define HINIC3_MIN_QUEUE_DEPTH         128
+
 #define PCI_DEV_TO_INTR_HANDLE(pci_dev) ((pci_dev)->intr_handle)
 
 #define HINIC3_PKT_RX_L4_CKSUM_BAD     RTE_MBUF_F_RX_L4_CKSUM_BAD
@@ -144,6 +147,8 @@ struct hinic3_nic_dev {
 
        uint16_t num_sqs;
        uint16_t num_rqs;
+       uint16_t rxq_depth;
+       uint16_t txq_depth;
        uint16_t max_sqs;
        uint16_t max_rqs;
 
diff --git a/drivers/net/hinic3/hinic3_nic_io.c 
b/drivers/net/hinic3/hinic3_nic_io.c
index c66748da2a..818c2cd548 100644
--- a/drivers/net/hinic3/hinic3_nic_io.c
+++ b/drivers/net/hinic3/hinic3_nic_io.c
@@ -514,11 +514,38 @@ hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev)
        uint32_t rq_depth = 0;
        uint32_t sq_depth = 0;
        uint16_t q_id;
+       uint16_t i;
        int err;
 
        if (!nic_dev)
                return -EINVAL;
 
+       /*
+        * The root context carries a single depth per direction, taken from
+        * queue 0, and a queue setup cannot change the other queues. A partial
+        * reconfiguration would therefore leave the rings sized differently
+        * from the root context, so refuse to start unless every configured
+        * queue is present and shares the depth of queue 0.
+        */
+       for (i = 0; i < nic_dev->num_rqs; i++) {
+               if (nic_dev->rxqs[i] == NULL ||
+                   nic_dev->rxqs[i]->q_depth != nic_dev->rxqs[0]->q_depth) {
+                       PMD_DRV_LOG(ERR,
+                                   "rxq%u is missing or has a different depth 
than rxq0.",
+                                   i);
+                       return -EINVAL;
+               }
+       }
+       for (i = 0; i < nic_dev->num_sqs; i++) {
+               if (nic_dev->txqs[i] == NULL ||
+                   nic_dev->txqs[i]->q_depth != nic_dev->txqs[0]->q_depth) {
+                       PMD_DRV_LOG(ERR,
+                                   "txq%u is missing or has a different depth 
than txq0.",
+                                   i);
+                       return -EINVAL;
+               }
+       }
+
        hwdev = nic_dev->hwdev;
 
        err = init_sq_ctxts(nic_dev);
-- 
2.33.0

Reply via email to