ethdev: check queue state before starting or stopping
authorPablo de Lara <pablo.de.lara.guarch@intel.com>
Wed, 16 Sep 2015 21:51:24 +0000 (22:51 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 4 Nov 2015 16:52:14 +0000 (17:52 +0100)
Following the same approach taken with dev_started field
in rte_eth_dev_data structure, this patch adds two new fields
in it, rx_queue_state and tx_queue_state arrays, which track
which queues have been started and which not.

This is important to avoid trying to start/stop twice a queue,
which will result in undefined behaviour
(which may cause RX/TX disruption).

Mind that only the PMDs which have queue_start/stop functions
have been changed to update this field, as the functions will
check the queue state before switching it.

Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
drivers/net/cxgbe/cxgbe_ethdev.c
drivers/net/enic/enic_ethdev.c
drivers/net/fm10k/fm10k_ethdev.c
drivers/net/i40e/i40e_ethdev_vf.c
drivers/net/i40e/i40e_rxtx.c
drivers/net/ixgbe/ixgbe_rxtx.c
lib/librte_ether/rte_ethdev.c
lib/librte_ether/rte_ethdev.h

index 7884642..3ef787d 100644 (file)
@@ -405,23 +405,33 @@ static int cxgbe_dev_configure(struct rte_eth_dev *eth_dev)
 static int cxgbe_dev_tx_queue_start(struct rte_eth_dev *eth_dev,
                                    uint16_t tx_queue_id)
 {
+       int ret;
        struct sge_eth_txq *txq = (struct sge_eth_txq *)
                                  (eth_dev->data->tx_queues[tx_queue_id]);
 
        dev_debug(NULL, "%s: tx_queue_id = %d\n", __func__, tx_queue_id);
 
-       return t4_sge_eth_txq_start(txq);
+       ret = t4_sge_eth_txq_start(txq);
+       if (ret == 0)
+               eth_dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+       return ret;
 }
 
 static int cxgbe_dev_tx_queue_stop(struct rte_eth_dev *eth_dev,
                                   uint16_t tx_queue_id)
 {
+       int ret;
        struct sge_eth_txq *txq = (struct sge_eth_txq *)
                                  (eth_dev->data->tx_queues[tx_queue_id]);
 
        dev_debug(NULL, "%s: tx_queue_id = %d\n", __func__, tx_queue_id);
 
-       return t4_sge_eth_txq_stop(txq);
+       ret = t4_sge_eth_txq_stop(txq);
+       if (ret == 0)
+               eth_dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+       return ret;
 }
 
 static int cxgbe_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
@@ -497,6 +507,7 @@ static void cxgbe_dev_tx_queue_release(void *q)
 static int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
                                    uint16_t rx_queue_id)
 {
+       int ret;
        struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
        struct adapter *adap = pi->adapter;
        struct sge_rspq *q;
@@ -505,12 +516,18 @@ static int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
                  __func__, pi->port_id, rx_queue_id);
 
        q = eth_dev->data->rx_queues[rx_queue_id];
-       return t4_sge_eth_rxq_start(adap, q);
+
+       ret = t4_sge_eth_rxq_start(adap, q);
+       if (ret == 0)
+               eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+       return ret;
 }
 
 static int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
                                   uint16_t rx_queue_id)
 {
+       int ret;
        struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
        struct adapter *adap = pi->adapter;
        struct sge_rspq *q;
@@ -519,7 +536,11 @@ static int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
                  __func__, pi->port_id, rx_queue_id);
 
        q = eth_dev->data->rx_queues[rx_queue_id];
-       return t4_sge_eth_rxq_stop(adap, q);
+       ret = t4_sge_eth_rxq_stop(adap, q);
+       if (ret == 0)
+               eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+       return ret;
 }
 
 static int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
index 1e1a5da..3888dbb 100644 (file)
@@ -193,6 +193,7 @@ static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev,
        ENICPMD_FUNC_TRACE();
 
        enic_start_wq(enic, queue_idx);
+       eth_dev->data->tx_queue_state[queue_idx] = RTE_ETH_QUEUE_STATE_STARTED;
 
        return 0;
 }
@@ -208,6 +209,8 @@ static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev,
        ret = enic_stop_wq(enic, queue_idx);
        if (ret)
                dev_err(enic, "error in stopping wq %d\n", queue_idx);
+       else
+               eth_dev->data->tx_queue_state[queue_idx] = RTE_ETH_QUEUE_STATE_STOPPED;
 
        return ret;
 }
@@ -220,6 +223,7 @@ static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
        ENICPMD_FUNC_TRACE();
 
        enic_start_rq(enic, queue_idx);
+       eth_dev->data->rx_queue_state[queue_idx] = RTE_ETH_QUEUE_STATE_STARTED;
 
        return 0;
 }
@@ -235,6 +239,8 @@ static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
        ret = enic_stop_rq(enic, queue_idx);
        if (ret)
                dev_err(enic, "error in stopping rq %d\n", queue_idx);
+       else
+               eth_dev->data->rx_queue_state[queue_idx] = RTE_ETH_QUEUE_STATE_STOPPED;
 
        return ret;
 }
index 5fc1e58..cf7ada7 100644 (file)
@@ -753,6 +753,7 @@ fm10k_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
                 */
                FM10K_WRITE_REG(hw, FM10K_RDH(rx_queue_id), 0);
                FM10K_WRITE_REG(hw, FM10K_RDT(rx_queue_id), rxq->nb_desc - 1);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        }
 
        return err;
@@ -771,6 +772,7 @@ fm10k_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 
                /* Free mbuf and clean HW ring */
                rx_queue_clean(dev->data->rx_queues[rx_queue_id]);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
@@ -800,6 +802,7 @@ fm10k_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
                FM10K_WRITE_REG(hw, FM10K_TXDCTL(tx_queue_id),
                                        FM10K_TXDCTL_ENABLE | txdctl);
                FM10K_WRITE_FLUSH(hw);
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        } else
                err = -1;
 
@@ -816,6 +819,7 @@ fm10k_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
        if (tx_queue_id < dev->data->nb_tx_queues) {
                tx_queue_disable(hw, tx_queue_id);
                tx_queue_clean(dev->data->tx_queues[tx_queue_id]);
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
index 615da8d..7ce8687 100644 (file)
@@ -1505,6 +1505,8 @@ i40evf_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
                if (err)
                        PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on",
                                    rx_queue_id);
+               else
+                       dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        }
 
        return err;
@@ -1529,6 +1531,7 @@ i40evf_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 
                i40e_rx_queue_release_mbufs(rxq);
                i40e_reset_rx_queue(rxq);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
@@ -1549,6 +1552,8 @@ i40evf_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
                if (err)
                        PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on",
                                    tx_queue_id);
+               else
+                       dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        }
 
        return err;
@@ -1573,6 +1578,7 @@ i40evf_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 
                i40e_tx_queue_release_mbufs(txq);
                i40e_reset_tx_queue(txq);
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
index e45c8f3..b60c356 100644 (file)
@@ -2006,7 +2006,8 @@ i40e_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 
                        i40e_rx_queue_release_mbufs(rxq);
                        i40e_reset_rx_queue(rxq);
-               }
+               } else
+                       dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        }
 
        return err;
@@ -2035,6 +2036,7 @@ i40e_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
                }
                i40e_rx_queue_release_mbufs(rxq);
                i40e_reset_rx_queue(rxq);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
@@ -2060,6 +2062,8 @@ i40e_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
                if (err)
                        PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on",
                                    tx_queue_id);
+               else
+                       dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        }
 
        return err;
@@ -2089,6 +2093,7 @@ i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 
                i40e_tx_queue_release_mbufs(txq);
                i40e_reset_tx_queue(txq);
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        }
 
        return 0;
index 2ba10e4..5561195 100644 (file)
@@ -4513,6 +4513,7 @@ ixgbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
                rte_wmb();
                IXGBE_WRITE_REG(hw, IXGBE_RDH(rxq->reg_idx), 0);
                IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), rxq->nb_rx_desc - 1);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        } else
                return -1;
 
@@ -4556,6 +4557,7 @@ ixgbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 
                ixgbe_rx_queue_release_mbufs(rxq);
                ixgbe_reset_rx_queue(adapter, rxq);
+               dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        } else
                return -1;
 
@@ -4598,6 +4600,7 @@ ixgbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
                rte_wmb();
                IXGBE_WRITE_REG(hw, IXGBE_TDH(txq->reg_idx), 0);
                IXGBE_WRITE_REG(hw, IXGBE_TDT(txq->reg_idx), 0);
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
        } else
                return -1;
 
@@ -4658,6 +4661,7 @@ ixgbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
                        txq->ops->release_mbufs(txq);
                        txq->ops->reset(txq);
                }
+               dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
        } else
                return -1;
 
index fcc9e0f..83704bb 100644 (file)
@@ -778,6 +778,13 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_start, -ENOTSUP);
 
+       if (dev->data->rx_queue_state[rx_queue_id] != RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already started\n",
+                       rx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->rx_queue_start(dev, rx_queue_id);
 
 }
@@ -801,6 +808,13 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_stop, -ENOTSUP);
 
+       if (dev->data->rx_queue_state[rx_queue_id] == RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already stopped\n",
+                       rx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->rx_queue_stop(dev, rx_queue_id);
 
 }
@@ -824,6 +838,13 @@ rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_start, -ENOTSUP);
 
+       if (dev->data->tx_queue_state[tx_queue_id] != RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already started\n",
+                       tx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->tx_queue_start(dev, tx_queue_id);
 
 }
@@ -847,6 +868,13 @@ rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_stop, -ENOTSUP);
 
+       if (dev->data->tx_queue_state[tx_queue_id] == RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already stopped\n",
+                       tx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->tx_queue_stop(dev, tx_queue_id);
 
 }
index 4f7b64b..eee1194 100644 (file)
@@ -919,6 +919,12 @@ struct rte_eth_dcb_info {
        struct rte_eth_dcb_tc_queue_mapping tc_queue;
 };
 
+/**
+ * RX/TX queue states
+ */
+#define RTE_ETH_QUEUE_STATE_STOPPED 0
+#define RTE_ETH_QUEUE_STATE_STARTED 1
+
 struct rte_eth_dev;
 
 struct rte_eth_dev_callback;
@@ -1553,6 +1559,10 @@ struct rte_eth_dev_data {
                all_multicast : 1, /**< RX all multicast mode ON(1) / OFF(0). */
                dev_started : 1,   /**< Device state: STARTED(1) / STOPPED(0). */
                lro         : 1;   /**< RX LRO is ON(1) / OFF(0) */
+       uint8_t rx_queue_state[RTE_MAX_QUEUES_PER_PORT];
+       /** Queues state: STARTED(1) / STOPPED(0) */
+       uint8_t tx_queue_state[RTE_MAX_QUEUES_PER_PORT];
+       /** Queues state: STARTED(1) / STOPPED(0) */
        uint32_t dev_flags; /**< Capabilities */
        enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough */
        int numa_node;  /**< NUMA node connection */