[dpdk-dev] [RFC] ether: support deferred queue setup

Qi Zhang qi.z.zhang at intel.com
Mon Jan 15 02:57:29 CET 2018


According to exist implementation, rte_eth_[rx|tx]_queue_setup will
always return fail if device is already started(rte_eth_dev_start).

This can't satisfied the usage when application want to deferred setup
part of the queues while keep traffic running on those queues already
be setup.

example:
rte_eth_dev_config(nb_rxq = 2, nb_txq =2)
rte_eth_rx_queue_setup(idx = 0 ...)
rte_eth_rx_queue_setup(idx = 0 ...)
rte_eth_dev_start(...) /* [rx|tx]_burst is ready to start on queue 0 */
rte_eth_rx_queue_setup(idx=1 ...) /* fail*/

Basically this is not a general hardware limitation, because for NIC like
i40e, ixgbe, it is not necessary to stop the whole device before configure
a fresh queue or reconfigure an exist queue with traffic on it.

The patch add new eth_dev_ops: [rx|tx]_queue_hot_[setup|release] and
internal logic of rte_eth_[rx|tx]_queue_setup is changed, so application
is allowed to setup queue after device start if the driver is implemented
properly.

The typical implementation of [rx|tx]_queue_hot_setup could be:
1. do the same thing in [rx|tx]_queue_setup.
2. perform per queue start logic from [rx|tx]_queue_start.

The typical implementation of [rx|tx]_queue_hot_release could be:
1. perform per queue stop logic from [rx|tx]_queue_stop.
2. do the same thing in [rx|tx]_queue_release.

Signed-off-by: Qi Zhang <qi.z.zhang at intel.com>
---
 lib/librte_ether/rte_ethdev.c | 54 ++++++++++++++++++++++++-------------------
 lib/librte_ether/rte_ethdev.h |  8 +++++++
 2 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a524af740..b4f534dbb 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1100,6 +1100,8 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
 	struct rte_eth_dev_info dev_info;
 	struct rte_eth_rxconf local_conf;
 	void **rxq;
+	eth_rx_queue_setup_t rxq_setup;
+	eth_queue_release_t rxq_release;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
@@ -1109,14 +1111,7 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
 		return -EINVAL;
 	}
 
-	if (dev->data->dev_started) {
-		RTE_PMD_DEBUG_TRACE(
-		    "port %d must be stopped to allow configuration\n", port_id);
-		return -EBUSY;
-	}
-
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_setup, -ENOTSUP);
 
 	/*
 	 * Check the size of the mbuf data buffer.
@@ -1158,11 +1153,19 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
 		return -EINVAL;
 	}
 
+	if (dev->data->dev_started) {
+		rxq_setup = dev->dev_ops->rx_queue_hot_setup;
+		rxq_release = dev->dev_ops->rx_queue_hot_release;
+	} else {
+		rxq_setup = dev->dev_ops->rx_queue_setup;
+		rxq_release = dev->dev_ops->rx_queue_release;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*rxq_setup, -ENOTSUP);
 	rxq = dev->data->rx_queues;
 	if (rxq[rx_queue_id]) {
-		RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_release,
-					-ENOTSUP);
-		(*dev->dev_ops->rx_queue_release)(rxq[rx_queue_id]);
+		RTE_FUNC_PTR_OR_ERR_RET(*rxq_release, -ENOTSUP);
+		(*rxq_release)(rxq[rx_queue_id]);
 		rxq[rx_queue_id] = NULL;
 	}
 
@@ -1179,8 +1182,8 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
 						    &local_conf.offloads);
 	}
 
-	ret = (*dev->dev_ops->rx_queue_setup)(dev, rx_queue_id, nb_rx_desc,
-					      socket_id, &local_conf, mp);
+	ret = (*rxq_setup)(dev, rx_queue_id, nb_rx_desc,
+				socket_id, &local_conf, mp);
 	if (!ret) {
 		if (!dev->data->min_rx_buf_size ||
 		    dev->data->min_rx_buf_size > mbp_buf_size)
@@ -1248,6 +1251,8 @@ rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
 	struct rte_eth_dev_info dev_info;
 	struct rte_eth_txconf local_conf;
 	void **txq;
+	eth_tx_queue_setup_t txq_setup;
+	eth_queue_release_t txq_release;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
@@ -1257,14 +1262,7 @@ rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
 		return -EINVAL;
 	}
 
-	if (dev->data->dev_started) {
-		RTE_PMD_DEBUG_TRACE(
-		    "port %d must be stopped to allow configuration\n", port_id);
-		return -EBUSY;
-	}
-
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_setup, -ENOTSUP);
 
 	rte_eth_dev_info_get(port_id, &dev_info);
 
@@ -1280,11 +1278,19 @@ rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
 		return -EINVAL;
 	}
 
+	if (dev->data->dev_started) {
+		txq_setup = dev->dev_ops->tx_queue_hot_setup;
+		txq_release = dev->dev_ops->tx_queue_hot_release;
+	} else {
+		txq_setup = dev->dev_ops->tx_queue_setup;
+		txq_release = dev->dev_ops->tx_queue_release;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*txq_setup, -ENOTSUP);
 	txq = dev->data->tx_queues;
 	if (txq[tx_queue_id]) {
-		RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_release,
-					-ENOTSUP);
-		(*dev->dev_ops->tx_queue_release)(txq[tx_queue_id]);
+		RTE_FUNC_PTR_OR_ERR_RET(*txq_release, -ENOTSUP);
+		(*txq_release)(txq[tx_queue_id]);
 		txq[tx_queue_id] = NULL;
 	}
 
@@ -1306,8 +1312,8 @@ rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
 					  &local_conf.offloads);
 	}
 
-	return (*dev->dev_ops->tx_queue_setup)(dev, tx_queue_id, nb_tx_desc,
-					       socket_id, &local_conf);
+	return (*txq_setup)(dev, tx_queue_id, nb_tx_desc, socket_id,
+				&local_conf);
 }
 
 void
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b10e2a92d..e78883e19 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1534,7 +1534,11 @@ struct eth_dev_ops {
 	eth_queue_start_t          tx_queue_start;/**< Start TX for a queue. */
 	eth_queue_stop_t           tx_queue_stop; /**< Stop TX for a queue. */
 	eth_rx_queue_setup_t       rx_queue_setup;/**< Set up device RX queue. */
+	eth_rx_queue_setup_t       rx_queue_hot_setup;
+	/**< Set up RX queue when device already started. */
 	eth_queue_release_t        rx_queue_release; /**< Release RX queue. */
+	eth_queue_release_t        rx_queue_hot_release;
+	/**< Release RX queue when device alrelady started. */
 	eth_rx_queue_count_t       rx_queue_count;
 	/**< Get the number of used RX descriptors. */
 	eth_rx_descriptor_done_t   rx_descriptor_done; /**< Check rxd DD bit. */
@@ -1545,7 +1549,11 @@ struct eth_dev_ops {
 	eth_rx_enable_intr_t       rx_queue_intr_enable;  /**< Enable Rx queue interrupt. */
 	eth_rx_disable_intr_t      rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
 	eth_tx_queue_setup_t       tx_queue_setup;/**< Set up device TX queue. */
+	eth_tx_queue_setup_t       tx_queue_hot_setup;
+	/**< Set up TX queue when device already started. */
 	eth_queue_release_t        tx_queue_release; /**< Release TX queue. */
+	eth_queue_release_t        tx_queue_hot_release;
+	/**< Release TX queue when device already started. */
 	eth_tx_done_cleanup_t      tx_done_cleanup;/**< Free tx ring mbufs */
 
 	eth_dev_led_on_t           dev_led_on;    /**< Turn on LED. */
-- 
2.13.6



More information about the dev mailing list