The Tx queue was set up first and left in place when the Rx queue
setup failed. A new setup of the same queue pair, either a retry after
such a failure or a reconfiguration, then overwrote the previous queue
pointers without freeing them.

Check the shared configuration before setting up any queue, release
the queues of a previous setup, and release the Tx queue if the Rx
queue setup fails. As the previous queues are released, refuse the
setup while the device is started.

Fixes: c39d1e082a4b ("raw/ntb: setup queues")
Cc: [email protected]

Suggested-by: Stephen Hemminger <[email protected]>
Signed-off-by: Raghavendra Ningoji <[email protected]>
---
 drivers/raw/ntb/ntb.c | 64 +++++++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 27 deletions(-)

diff --git a/drivers/raw/ntb/ntb.c b/drivers/raw/ntb/ntb.c
index 8b1c332fbb..68137c4237 100644
--- a/drivers/raw/ntb/ntb.c
+++ b/drivers/raw/ntb/ntb.c
@@ -235,10 +235,8 @@ ntb_rxq_release_mbufs(struct ntb_rx_queue *q)
 static void
 ntb_rxq_release(struct ntb_rx_queue *rxq)
 {
-       if (!rxq) {
-               NTB_LOG(ERR, "Pointer to rxq is NULL");
+       if (!rxq)
                return;
-       }
 
        ntb_rxq_release_mbufs(rxq);
 
@@ -273,11 +271,6 @@ ntb_rxq_setup(struct rte_rawdev *dev,
        if (conf_size != sizeof(*rxq_conf))
                return -EINVAL;
 
-       if (rxq_conf->rx_mp == NULL) {
-               NTB_LOG(ERR, "Invalid null mempool pointer.");
-               return -EINVAL;
-       }
-
        if (ntb_queue_nb_desc_check(rxq_conf->nb_desc) < 0)
                return -EINVAL;
 
@@ -338,10 +331,8 @@ ntb_txq_release_mbufs(struct ntb_tx_queue *q)
 static void
 ntb_txq_release(struct ntb_tx_queue *txq)
 {
-       if (!txq) {
-               NTB_LOG(ERR, "Pointer to txq is NULL");
+       if (!txq)
                return;
-       }
 
        ntb_txq_release_mbufs(txq);
 
@@ -422,43 +413,62 @@ ntb_txq_setup(struct rte_rawdev *dev,
 }
 
 
+static int
+ntb_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
+{
+       struct ntb_hw *hw = dev->dev_private;
+
+       if (queue_id >= hw->queue_pairs)
+               return -EINVAL;
+
+       ntb_txq_release(hw->tx_queues[queue_id]);
+       hw->tx_queues[queue_id] = NULL;
+       ntb_rxq_release(hw->rx_queues[queue_id]);
+       hw->rx_queues[queue_id] = NULL;
+
+       return 0;
+}
+
 static int
 ntb_queue_setup(struct rte_rawdev *dev,
                uint16_t queue_id,
                rte_rawdev_obj_t queue_conf,
                size_t conf_size)
 {
+       struct ntb_queue_conf *conf = queue_conf;
        struct ntb_hw *hw = dev->dev_private;
        int ret;
 
        if (queue_id >= hw->queue_pairs)
                return -EINVAL;
 
+       if (conf == NULL || conf_size != sizeof(*conf))
+               return -EINVAL;
+
+       if (conf->rx_mp == NULL) {
+               NTB_LOG(ERR, "Invalid null mempool pointer.");
+               return -EINVAL;
+       }
+
+       if (dev->started) {
+               NTB_LOG(ERR, "Cannot setup queue %u of a started device.", 
queue_id);
+               return -EBUSY;
+       }
+
+       /* Release the queues of a previous setup. */
+       ntb_queue_release(dev, queue_id);
+
        ret = ntb_txq_setup(dev, queue_id, queue_conf, conf_size);
        if (ret < 0)
                return ret;
 
        ret = ntb_rxq_setup(dev, queue_id, queue_conf, conf_size);
+       if (ret < 0)
+               ntb_queue_release(dev, queue_id);
 
        return ret;
 }
 
-static int
-ntb_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
-{
-       struct ntb_hw *hw = dev->dev_private;
-
-       if (queue_id >= hw->queue_pairs)
-               return -EINVAL;
-
-       ntb_txq_release(hw->tx_queues[queue_id]);
-       hw->tx_queues[queue_id] = NULL;
-       ntb_rxq_release(hw->rx_queues[queue_id]);
-       hw->rx_queues[queue_id] = NULL;
-
-       return 0;
-}
-
 static uint16_t
 ntb_queue_count(struct rte_rawdev *dev)
 {
-- 
2.34.1

Reply via email to