DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 1/3] eventdev/eth_tx: add queue start stop API
@ 2022-09-09  3:42 Naga Harish K S V
  2022-09-09  3:42 ` [PATCH 2/3] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-09  3:42 UTC (permalink / raw)
  To: jay.jayatheerthan, jerinj; +Cc: dev

This patch adds support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx Adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx Adapter from transmitting any
mbufs to the Tx queue. The Tx Adapter also frees any mbufs
that it may have buffered for this queue. All inflight packets
destined to the queue are freed until the queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 lib/eventdev/eventdev_pmd.h             |  41 +++++++++
 lib/eventdev/rte_event_eth_tx_adapter.c | 114 +++++++++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h |  39 ++++++++
 lib/eventdev/version.map                |   2 +
 4 files changed, 192 insertions(+), 4 deletions(-)

diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index f514a37575..a27c0883c6 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to TX adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device TX queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to TX adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device TX queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index aaef352f5c..f2e426d6ab 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -557,7 +565,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -571,7 +579,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -608,7 +617,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -672,7 +682,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -867,6 +878,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -885,6 +897,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -930,6 +956,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1320,3 +1348,81 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static int
+txa_queue_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id, bool state)
+{
+	struct txa_service_data *txa;
+	struct txa_service_queue_info *tqi;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+				      tx_queue_id,
+				      &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						      eth_dev_id,
+						      &caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (state == true) {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+				txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id)
+						: -EINVAL;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		tqi->stopped = false;
+		rte_spinlock_unlock(&txa->tx_lock);
+	} else {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+				txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id)
+						: -EINVAL;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		txa_txq_buffer_drain(tqi);
+		tqi->stopped = true;
+		rte_spinlock_unlock(&txa->tx_lock);
+	}
+	return 0;
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..77e394e1ac 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,43 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the Tx Adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resuming enqueueing events that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx Adapter from transmitting any mbufs to the
+ * <eth_dev_id, tx_queue_id>. The Tx Adapter also frees any mbufs
+ * that it may have buffered for this queue.
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 2/3] test/eth_tx: add testcase for queue start stop APIs
  2022-09-09  3:42 [PATCH 1/3] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-09  3:42 ` Naga Harish K S V
  2022-09-09  3:42 ` [PATCH 3/3] doc: added eth Tx adapter " Naga Harish K S V
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-09  3:42 UTC (permalink / raw)
  To: jay.jayatheerthan, jerinj; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 3/3] doc: added eth Tx adapter queue start stop APIs
  2022-09-09  3:42 [PATCH 1/3] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-09  3:42 ` [PATCH 2/3] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
@ 2022-09-09  3:42 ` Naga Harish K S V
  2022-09-14 15:20 ` [PATCH 1/3] eventdev/eth_tx: add queue start stop API Jerin Jacob
  2022-09-15  9:53 ` [PATCH v2 1/2] " Naga Harish K S V
  3 siblings, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-09  3:42 UTC (permalink / raw)
  To: jay.jayatheerthan, jerinj; +Cc: dev

Added tx adapter queue start - rte_event_eth_rx_adapter_queue_start()
and tx adapter queue stop - rte_event_eth_tx_adapter_queue_stop()

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 doc/guides/rel_notes/release_22_11.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c32c18ff49..dc1060660c 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -29,6 +29,10 @@ New Features
   ethernet device id and Rx queue index.
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_start`` to stop the Tx Adapter from transmitting any
+  mbufs to the Tx_queue.
 
 .. This section should contain new features added in this release.
    Sample format:
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
  2022-09-09  3:42 [PATCH 1/3] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-09  3:42 ` [PATCH 2/3] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-09  3:42 ` [PATCH 3/3] doc: added eth Tx adapter " Naga Harish K S V
@ 2022-09-14 15:20 ` Jerin Jacob
  2022-09-16  5:21   ` Naga Harish K, S V
  2022-09-16  6:10   ` Jayatheerthan, Jay
  2022-09-15  9:53 ` [PATCH v2 1/2] " Naga Harish K S V
  3 siblings, 2 replies; 20+ messages in thread
From: Jerin Jacob @ 2022-09-14 15:20 UTC (permalink / raw)
  To: Naga Harish K S V; +Cc: jay.jayatheerthan, jerinj, dev

On Fri, Sep 9, 2022 at 9:12 AM Naga Harish K S V
<s.v.naga.harish.k@intel.com> wrote:
>
> This patch adds support to start or stop a particular queue
> that is associated with the adapter.
>
> Start function enables the Tx Adapter to start enqueueing
> packets to the Tx queue.
>
> Stop function stops the Tx Adapter from transmitting any
> mbufs to the Tx queue. The Tx Adapter also frees any mbufs
> that it may have buffered for this queue. All inflight packets
> destined to the queue are freed until the queue is started again.
>
> Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>

In general, new APIs look good to me if it is helping the SW driver.
I will wait for comment from @Jayatheerthan, Jay

Some comments below

> ---
>  lib/eventdev/eventdev_pmd.h             |  41 +++++++++
>  lib/eventdev/rte_event_eth_tx_adapter.c | 114 +++++++++++++++++++++++-
>  lib/eventdev/rte_event_eth_tx_adapter.h |  39 ++++++++
>  lib/eventdev/version.map                |   2 +

Please squash 3/3 to 1/3.

Please update doc/guides/prog_guide/event_ethernet_tx_adapter.rst for
new APIs doc for
What is this API and when to use this API etc.


>  4 files changed, 192 insertions(+), 4 deletions(-)
>
> diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
> index f514a37575..a27c0883c6 100644
> --- a/lib/eventdev/eventdev_pmd.h
> +++ b/lib/eventdev/eventdev_pmd.h
> @@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
>  typedef int (*eventdev_eth_tx_adapter_instance_get_t)
>         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
>
> +/**
> + * Start a Tx queue that is assigned to TX adapter instance

Tx adapter

> + *
> + * @param id
> + *  Adapter identifier
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device
> + *
> + * @param tx_queue_id
> + *  Ethernet device TX queue index

Tx

> + *
> + * @return
> + *  -  0: Success
> + *  - <0: Error code on failure
> + */
> +typedef int (*eventdev_eth_tx_adapter_queue_start)
> +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> +
> +/**
> + * Stop a Tx queue that is assigned to TX adapter instance

Tx

> +int
> +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
> +{
> +       return txa_queue_state_set(eth_dev_id, tx_queue_id, true);

Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is NULL

> +}
> +
> +int
> +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
> +{
> +       return txa_queue_state_set(eth_dev_id, tx_queue_id, false);

Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is NULL

> +}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-09  3:42 [PATCH 1/3] eventdev/eth_tx: add queue start stop API Naga Harish K S V
                   ` (2 preceding siblings ...)
  2022-09-14 15:20 ` [PATCH 1/3] eventdev/eth_tx: add queue start stop API Jerin Jacob
@ 2022-09-15  9:53 ` Naga Harish K S V
  2022-09-15  9:53   ` [PATCH v2 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  3 siblings, 2 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-15  9:53 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

This patch adds support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx Adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx Adapter from transmitting any
mbufs to the Tx queue. The Tx Adapter also frees any mbufs
that it may have buffered for this queue. All inflight packets
destined to the queue are freed until the queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 .../prog_guide/event_ethernet_tx_adapter.rst  |  16 +++
 doc/guides/rel_notes/release_22_11.rst        |   8 ++
 lib/eventdev/eventdev_pmd.h                   |  41 +++++++
 lib/eventdev/rte_event_eth_tx_adapter.c       | 112 +++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h       |  39 ++++++
 lib/eventdev/version.map                      |   2 +
 6 files changed, 214 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
index 4da9bcda3a..bfd13878c0 100644
--- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
+++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
@@ -182,3 +182,19 @@ mbufs are destined to the same ethernet port and queue by setting the bit
 ``rte_event_vector::queue``.
 If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
 into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The Tx adapter can be configured to start/stop enqueueing of packets to a NIC
+queue using ``rte_event_eth_tx_adapter_queue_start()`` and
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+Start function enables the Tx Adapter runtime to start enqueueing packets
+to the Tx queue.
+
+Stop function stops the Tx Adapter runtime function from enqueueing any
+packets to the assiciated Tx queue. This API also frees any packets that
+it may have buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c32c18ff49..ec05ddcbf5 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -30,6 +30,14 @@ New Features
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
 
+
+* **Added Tx adapter queue start/stop API**
+
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from transmitting any
+  packets to the Tx queue.
+
 .. This section should contain new features added in this release.
    Sample format:
 
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index f514a37575..31eaf927df 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 7e82fe030c..e0aaf3bbe9 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1319,3 +1347,79 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static int
+txa_queue_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id, bool state)
+{
+	struct txa_service_data *txa;
+	struct txa_service_queue_info *tqi;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+				      tx_queue_id,
+				      &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						      eth_dev_id,
+						      &caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (state == true) {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+				txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id) : 0;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		tqi->stopped = false;
+		rte_spinlock_unlock(&txa->tx_lock);
+	} else {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+				txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id) : 0;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		txa_txq_buffer_drain(tqi);
+		tqi->stopped = true;
+		rte_spinlock_unlock(&txa->tx_lock);
+	}
+	return 0;
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..77e394e1ac 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,43 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the Tx Adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resuming enqueueing events that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx Adapter from transmitting any mbufs to the
+ * <eth_dev_id, tx_queue_id>. The Tx Adapter also frees any mbufs
+ * that it may have buffered for this queue.
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 2/2] test/eth_tx: add testcase for queue start stop APIs
  2022-09-15  9:53 ` [PATCH v2 1/2] " Naga Harish K S V
@ 2022-09-15  9:53   ` Naga Harish K S V
  2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  1 sibling, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-15  9:53 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-15  9:53 ` [PATCH v2 1/2] " Naga Harish K S V
  2022-09-15  9:53   ` [PATCH v2 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
@ 2022-09-15 15:19   ` Naga Harish K S V
  2022-09-15 15:19     ` [PATCH v3 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
                       ` (2 more replies)
  1 sibling, 3 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-15 15:19 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Add support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx adapter from transmitting any
packets to the Tx queue. The Tx adapter also frees any packets
that may have been buffered for this queue. All inflight packets
destined to the queue are freed by the adapter runtime until the
queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
v3:
* fix documentation and address review comments
---
 .../prog_guide/event_ethernet_tx_adapter.rst  |  16 +++
 doc/guides/rel_notes/release_22_11.rst        |   8 ++
 lib/eventdev/eventdev_pmd.h                   |  41 +++++++
 lib/eventdev/rte_event_eth_tx_adapter.c       | 113 +++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h       |  42 +++++++
 lib/eventdev/version.map                      |   2 +
 6 files changed, 218 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
index 4da9bcda3a..8eb1548cd5 100644
--- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
+++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
@@ -182,3 +182,19 @@ mbufs are destined to the same ethernet port and queue by setting the bit
 ``rte_event_vector::queue``.
 If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
 into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The adapter can be configured to start/stop enqueueing of packets to a NIC
+queue using ``rte_event_eth_tx_adapter_queue_start()`` or
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+Start function enables the adapter runtime to start enqueueing packets
+to the Tx queue.
+
+Stop function stops the adapter runtime function from enqueueing any
+packets to the associated Tx queue. This API also frees any packets that
+may have been buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c32c18ff49..ec05ddcbf5 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -30,6 +30,14 @@ New Features
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
 
+
+* **Added Tx adapter queue start/stop API**
+
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from transmitting any
+  packets to the Tx queue.
+
 .. This section should contain new features added in this release.
    Sample format:
 
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index f514a37575..31eaf927df 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 7e82fe030c..60baf421be 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1319,3 +1347,80 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static int
+txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			  bool start_state)
+{
+	struct txa_service_data *txa;
+	struct txa_service_queue_info *tqi = NULL;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+						    tx_queue_id,
+						    &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						eth_dev_id,
+						&caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (start_state == true) {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+				txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id) : 0;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		tqi->stopped = !start_state;
+		rte_spinlock_unlock(&txa->tx_lock);
+	} else {
+		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+				txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							eth_dev_id,
+							tx_queue_id) : 0;
+			return ret;
+		}
+		rte_spinlock_lock(&txa->tx_lock);
+		tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+		if (unlikely(tqi == NULL || !tqi->added)) {
+			rte_spinlock_unlock(&txa->tx_lock);
+			return -EINVAL;
+		}
+		txa_txq_buffer_drain(tqi);
+		tqi->stopped = !start_state;
+		rte_spinlock_unlock(&txa->tx_lock);
+	}
+	return 0;
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..2c387784da 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,46 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the Tx adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resume enqueueing packets that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ * @see rte_event_eth_tx_adapter_queue_stop
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx adapter runtime function from enqueueing any packets
+ * to the associated Tx queue. This API also frees any packets that may
+ * have been buffered for this queue. All inflight packets destined to the
+ * queue are freed by the adapter runtime until the queue is started again.
+ * @see rte_event_eth_tx_adapter_queue_start
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 2/2] test/eth_tx: add testcase for queue start stop APIs
  2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-15 15:19     ` Naga Harish K S V
  2022-09-16 15:15     ` [PATCH v4 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-16 16:23     ` [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2 siblings, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-15 15:19 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
  2022-09-14 15:20 ` [PATCH 1/3] eventdev/eth_tx: add queue start stop API Jerin Jacob
@ 2022-09-16  5:21   ` Naga Harish K, S V
  2022-09-16  6:10   ` Jayatheerthan, Jay
  1 sibling, 0 replies; 20+ messages in thread
From: Naga Harish K, S V @ 2022-09-16  5:21 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: Jayatheerthan, Jay, jerinj, dev



> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Wednesday, September 14, 2022 8:51 PM
> To: Naga Harish K, S V <s.v.naga.harish.k@intel.com>
> Cc: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>; jerinj@marvell.com;
> dev@dpdk.org
> Subject: Re: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
> 
> On Fri, Sep 9, 2022 at 9:12 AM Naga Harish K S V
> <s.v.naga.harish.k@intel.com> wrote:
> >
> > This patch adds support to start or stop a particular queue that is
> > associated with the adapter.
> >
> > Start function enables the Tx Adapter to start enqueueing packets to
> > the Tx queue.
> >
> > Stop function stops the Tx Adapter from transmitting any mbufs to the
> > Tx queue. The Tx Adapter also frees any mbufs that it may have
> > buffered for this queue. All inflight packets destined to the queue
> > are freed until the queue is started again.
> >
> > Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
> 
> In general, new APIs look good to me if it is helping the SW driver.
> I will wait for comment from @Jayatheerthan, Jay
> 
> Some comments below
> 

Posted V3 version with all comments addressed

> > ---
> >  lib/eventdev/eventdev_pmd.h             |  41 +++++++++
> >  lib/eventdev/rte_event_eth_tx_adapter.c | 114
> > +++++++++++++++++++++++-  lib/eventdev/rte_event_eth_tx_adapter.h
> |  39 ++++++++
> >  lib/eventdev/version.map                |   2 +
> 
> Please squash 3/3 to 1/3.
> 
> Please update doc/guides/prog_guide/event_ethernet_tx_adapter.rst for
> new APIs doc for What is this API and when to use this API etc.
> 
> 
> >  4 files changed, 192 insertions(+), 4 deletions(-)
> >
> > diff --git a/lib/eventdev/eventdev_pmd.h
> b/lib/eventdev/eventdev_pmd.h
> > index f514a37575..a27c0883c6 100644
> > --- a/lib/eventdev/eventdev_pmd.h
> > +++ b/lib/eventdev/eventdev_pmd.h
> > @@ -1294,6 +1294,43 @@ typedef int
> > (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,  typedef int
> (*eventdev_eth_tx_adapter_instance_get_t)
> >         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t
> > *txa_inst_id);
> >
> > +/**
> > + * Start a Tx queue that is assigned to TX adapter instance
> 
> Tx adapter
> 
> > + *
> > + * @param id
> > + *  Adapter identifier
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device
> > + *
> > + * @param tx_queue_id
> > + *  Ethernet device TX queue index
> 
> Tx
> 
> > + *
> > + * @return
> > + *  -  0: Success
> > + *  - <0: Error code on failure
> > + */
> > +typedef int (*eventdev_eth_tx_adapter_queue_start)
> > +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> > +
> > +/**
> > + * Stop a Tx queue that is assigned to TX adapter instance
> 
> Tx
> 
> > +int
> > +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t
> > +tx_queue_id) {
> > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
> 
> Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is
> NULL
> 
> > +}
> > +
> > +int
> > +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t
> > +tx_queue_id) {
> > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
> 
> Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is
> NULL
> 
> > +}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
  2022-09-14 15:20 ` [PATCH 1/3] eventdev/eth_tx: add queue start stop API Jerin Jacob
  2022-09-16  5:21   ` Naga Harish K, S V
@ 2022-09-16  6:10   ` Jayatheerthan, Jay
  2022-09-16 15:18     ` Naga Harish K, S V
  1 sibling, 1 reply; 20+ messages in thread
From: Jayatheerthan, Jay @ 2022-09-16  6:10 UTC (permalink / raw)
  To: Jerin Jacob, Naga Harish K, S V; +Cc: jerinj, dev

> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Wednesday, September 14, 2022 8:51 PM
> To: Naga Harish K, S V <s.v.naga.harish.k@intel.com>
> Cc: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>; jerinj@marvell.com; dev@dpdk.org
> Subject: Re: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
> 
> On Fri, Sep 9, 2022 at 9:12 AM Naga Harish K S V
> <s.v.naga.harish.k@intel.com> wrote:
> >
> > This patch adds support to start or stop a particular queue
> > that is associated with the adapter.
> >
> > Start function enables the Tx Adapter to start enqueueing
> > packets to the Tx queue.
> >
> > Stop function stops the Tx Adapter from transmitting any
> > mbufs to the Tx queue. The Tx Adapter also frees any mbufs
> > that it may have buffered for this queue. All inflight packets
> > destined to the queue are freed until the queue is started again.
> >
> > Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
> 
> In general, new APIs look good to me if it is helping the SW driver.
> I will wait for comment from @Jayatheerthan, Jay

Yes @jerin, these APIs help avoid some unexpected behavior with application stopping ethdev Tx queues and Tx adapter being unaware of it. With these APIs, the application can call stop API to notify Tx adapter that corresponding ethdev Tx queue is stopped and any in-flight packets are freed by Tx adapter dataplane code. Tx adapter stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue is enabled, application can notify Tx adapter to resume processing of the packets for that queue by calling the start API. The ethdev Tx queue is started before calling Tx adapter start API.

Perhaps, some of this usecase description can go into event_ethernet_tx_adapter.rst and doxygen comments for the APIs. @Harish, could you add please ?

> 
> Some comments below
> 
> > ---
> >  lib/eventdev/eventdev_pmd.h             |  41 +++++++++
> >  lib/eventdev/rte_event_eth_tx_adapter.c | 114 +++++++++++++++++++++++-
> >  lib/eventdev/rte_event_eth_tx_adapter.h |  39 ++++++++
> >  lib/eventdev/version.map                |   2 +
> 
> Please squash 3/3 to 1/3.
> 
> Please update doc/guides/prog_guide/event_ethernet_tx_adapter.rst for
> new APIs doc for
> What is this API and when to use this API etc.
> 
> 
> >  4 files changed, 192 insertions(+), 4 deletions(-)
> >
> > diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
> > index f514a37575..a27c0883c6 100644
> > --- a/lib/eventdev/eventdev_pmd.h
> > +++ b/lib/eventdev/eventdev_pmd.h
> > @@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
> >  typedef int (*eventdev_eth_tx_adapter_instance_get_t)
> >         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
> >
> > +/**
> > + * Start a Tx queue that is assigned to TX adapter instance
> 
> Tx adapter
> 
> > + *
> > + * @param id
> > + *  Adapter identifier
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device
> > + *
> > + * @param tx_queue_id
> > + *  Ethernet device TX queue index
> 
> Tx
> 
> > + *
> > + * @return
> > + *  -  0: Success
> > + *  - <0: Error code on failure
> > + */
> > +typedef int (*eventdev_eth_tx_adapter_queue_start)
> > +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> > +
> > +/**
> > + * Stop a Tx queue that is assigned to TX adapter instance
> 
> Tx
> 
> > +int
> > +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
> > +{
> > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
> 
> Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is NULL
> 
> > +}
> > +
> > +int
> > +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
> > +{
> > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
> 
> Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is NULL
> 
> > +}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v4 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-15 15:19     ` [PATCH v3 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
@ 2022-09-16 15:15     ` Naga Harish K S V
  2022-09-16 15:15       ` [PATCH v4 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-16 16:23     ` [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2 siblings, 1 reply; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-16 15:15 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Add support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx adapter from transmitting any
packets to the Tx queue. The Tx adapter also frees any packets
that may have been buffered for this queue. All inflight packets
destined to the queue are freed by the adapter runtime until the
queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
v4:
* update programmer guide and doxygen comments
v3:
* fix documentation and address review comments
---
 .../prog_guide/event_ethernet_tx_adapter.rst  |  25 ++++
 doc/guides/rel_notes/release_22_11.rst        |   8 ++
 lib/eventdev/eventdev_pmd.h                   |  41 +++++++
 lib/eventdev/rte_event_eth_tx_adapter.c       | 113 +++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h       |  54 +++++++++
 lib/eventdev/version.map                      |   2 +
 6 files changed, 239 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
index 4da9bcda3a..d1fdf9a6d1 100644
--- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
+++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
@@ -182,3 +182,28 @@ mbufs are destined to the same ethernet port and queue by setting the bit
 ``rte_event_vector::queue``.
 If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
 into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The adapter can be configured to start/stop enqueueing of packets to a NIC
+queue using ``rte_event_eth_tx_adapter_queue_start()`` or
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+These APIs help avoid some unexpected behavior with application stopping ethdev
+Tx queues and adapter being unaware of it. With these APIs, the application can
+call stop API to notify adapter that corresponding ethdev Tx queue is stopped
+and any in-flight packets are freed by adapter dataplane code. Adapter queue
+stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue
+is enabled, application can notify adapter to resume processing of the packets
+for that queue by calling the start API. The ethdev Tx queue is started before
+calling adapter start API.
+
+Start function enables the adapter runtime to start enqueueing packets
+to the Tx queue.
+
+Stop function stops the adapter runtime function from enqueueing any
+packets to the associated Tx queue. This API also frees any packets that
+may have been buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c32c18ff49..ec05ddcbf5 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -30,6 +30,14 @@ New Features
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
 
+
+* **Added Tx adapter queue start/stop API**
+
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from transmitting any
+  packets to the Tx queue.
+
 .. This section should contain new features added in this release.
    Sample format:
 
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index f514a37575..31eaf927df 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 7e82fe030c..5fb6a09f2d 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1319,3 +1347,80 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static inline int
+txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			     bool start_state, struct txa_service_data *txa)
+{
+	struct txa_service_queue_info *tqi = NULL;
+
+	rte_spinlock_lock(&txa->tx_lock);
+	tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+	if (unlikely(tqi == NULL || !tqi->added)) {
+		rte_spinlock_unlock(&txa->tx_lock);
+		return -EINVAL;
+	}
+	if (start_state == false)
+		txa_txq_buffer_drain(tqi);
+
+	tqi->stopped = !start_state;
+	rte_spinlock_unlock(&txa->tx_lock);
+	return 0;
+}
+
+static int
+txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			  bool start_state)
+{
+	struct txa_service_data *txa;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+						    tx_queue_id,
+						    &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						eth_dev_id,
+						&caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+		if (start_state == true) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+			      txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							       eth_dev_id,
+							       tx_queue_id) : 0;
+		} else {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+			      txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							      eth_dev_id,
+							      tx_queue_id) : 0;
+		}
+		return ret;
+	}
+	return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
+					    start_state, txa);
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..54d7a32b94 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,58 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the Tx adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resume enqueueing packets that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ * @see rte_event_eth_tx_adapter_queue_stop
+ *
+ * Use case:
+ * ~~~~~~~~
+ * The queue start/stop APIs help avoid some unexpected behavior with
+ * application stopping ethdev Tx queues and adapter being unaware of it.
+ * With these APIs, the application can call stop API to notify adapter
+ * that corresponding ethdev Tx queue is stopped and any in-flight
+ * packets are freed by adapter dataplane code. Adapter queue stop API
+ * is called before stopping the ethdev Tx queue. When ethdev Tx queue
+ * is enabled, application can notify adapter to resume processing of
+ * the packets for that queue by calling the start API. The ethdev Tx
+ * queue is started before calling adapter start API.
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx adapter runtime function from enqueueing any packets
+ * to the associated Tx queue. This API also frees any packets that may
+ * have been buffered for this queue. All inflight packets destined to the
+ * queue are freed by the adapter runtime until the queue is started again.
+ * @see rte_event_eth_tx_adapter_queue_start
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v4 2/2] test/eth_tx: add testcase for queue start stop APIs
  2022-09-16 15:15     ` [PATCH v4 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-16 15:15       ` Naga Harish K S V
  0 siblings, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-16 15:15 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
  2022-09-16  6:10   ` Jayatheerthan, Jay
@ 2022-09-16 15:18     ` Naga Harish K, S V
  0 siblings, 0 replies; 20+ messages in thread
From: Naga Harish K, S V @ 2022-09-16 15:18 UTC (permalink / raw)
  To: Jayatheerthan, Jay, Jerin Jacob; +Cc: jerinj, dev



> -----Original Message-----
> From: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>
> Sent: Friday, September 16, 2022 11:40 AM
> To: Jerin Jacob <jerinjacobk@gmail.com>; Naga Harish K, S V
> <s.v.naga.harish.k@intel.com>
> Cc: jerinj@marvell.com; dev@dpdk.org
> Subject: RE: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
> 
> > -----Original Message-----
> > From: Jerin Jacob <jerinjacobk@gmail.com>
> > Sent: Wednesday, September 14, 2022 8:51 PM
> > To: Naga Harish K, S V <s.v.naga.harish.k@intel.com>
> > Cc: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>;
> > jerinj@marvell.com; dev@dpdk.org
> > Subject: Re: [PATCH 1/3] eventdev/eth_tx: add queue start stop API
> >
> > On Fri, Sep 9, 2022 at 9:12 AM Naga Harish K S V
> > <s.v.naga.harish.k@intel.com> wrote:
> > >
> > > This patch adds support to start or stop a particular queue that is
> > > associated with the adapter.
> > >
> > > Start function enables the Tx Adapter to start enqueueing packets to
> > > the Tx queue.
> > >
> > > Stop function stops the Tx Adapter from transmitting any mbufs to
> > > the Tx queue. The Tx Adapter also frees any mbufs that it may have
> > > buffered for this queue. All inflight packets destined to the queue
> > > are freed until the queue is started again.
> > >
> > > Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
> >
> > In general, new APIs look good to me if it is helping the SW driver.
> > I will wait for comment from @Jayatheerthan, Jay
> 
> Yes @jerin, these APIs help avoid some unexpected behavior with
> application stopping ethdev Tx queues and Tx adapter being unaware of it.
> With these APIs, the application can call stop API to notify Tx adapter that
> corresponding ethdev Tx queue is stopped and any in-flight packets are
> freed by Tx adapter dataplane code. Tx adapter stop API is called before
> stopping the ethdev Tx queue. When ethdev Tx queue is enabled,
> application can notify Tx adapter to resume processing of the packets for that
> queue by calling the start API. The ethdev Tx queue is started before calling
> Tx adapter start API.
> 
> Perhaps, some of this usecase description can go into
> event_ethernet_tx_adapter.rst and doxygen comments for the APIs.
> @Harish, could you add please ?
> 

Included the above use case description in programmer guide and doxygen comments
In V4 version of the patch set.

> >
> > Some comments below
> >
> > > ---
> > >  lib/eventdev/eventdev_pmd.h             |  41 +++++++++
> > >  lib/eventdev/rte_event_eth_tx_adapter.c | 114
> > > +++++++++++++++++++++++-
> lib/eventdev/rte_event_eth_tx_adapter.h |  39 ++++++++
> > >  lib/eventdev/version.map                |   2 +
> >
> > Please squash 3/3 to 1/3.
> >
> > Please update doc/guides/prog_guide/event_ethernet_tx_adapter.rst for
> > new APIs doc for What is this API and when to use this API etc.
> >
> >
> > >  4 files changed, 192 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/lib/eventdev/eventdev_pmd.h
> > > b/lib/eventdev/eventdev_pmd.h index f514a37575..a27c0883c6 100644
> > > --- a/lib/eventdev/eventdev_pmd.h
> > > +++ b/lib/eventdev/eventdev_pmd.h
> > > @@ -1294,6 +1294,43 @@ typedef int
> > > (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,  typedef int
> (*eventdev_eth_tx_adapter_instance_get_t)
> > >         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t
> > > *txa_inst_id);
> > >
> > > +/**
> > > + * Start a Tx queue that is assigned to TX adapter instance
> >
> > Tx adapter
> >
> > > + *
> > > + * @param id
> > > + *  Adapter identifier
> > > + *
> > > + * @param eth_dev_id
> > > + *  Port identifier of Ethernet device
> > > + *
> > > + * @param tx_queue_id
> > > + *  Ethernet device TX queue index
> >
> > Tx
> >
> > > + *
> > > + * @return
> > > + *  -  0: Success
> > > + *  - <0: Error code on failure
> > > + */
> > > +typedef int (*eventdev_eth_tx_adapter_queue_start)
> > > +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> > > +
> > > +/**
> > > + * Stop a Tx queue that is assigned to TX adapter instance
> >
> > Tx
> >
> > > +int
> > > +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t
> > > +tx_queue_id) {
> > > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
> >
> > Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is
> > NULL
> >
> > > +}
> > > +
> > > +int
> > > +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t
> > > +tx_queue_id) {
> > > +       return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
> >
> > Make it is NOP with return 0 if eventdev_eth_tx_adapter_queue_start is
> > NULL
> >
> > > +}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-15 15:19     ` [PATCH v3 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-16 15:15     ` [PATCH v4 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-16 16:23     ` Naga Harish K S V
  2022-09-16 16:23       ` [PATCH v5 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-26  2:04       ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2 siblings, 2 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-16 16:23 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Add support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx adapter from transmitting any
packets to the Tx queue. The Tx adapter also frees any packets
that may have been buffered for this queue. All inflight packets
destined to the queue are freed by the adapter runtime until the
queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
v5:
* fix build failure
v4:
* update programmer guide and doxygen comments
v3:
* fix documentation and address review comments
---
 .../prog_guide/event_ethernet_tx_adapter.rst  |  25 ++++
 doc/guides/rel_notes/release_22_11.rst        |   8 ++
 lib/eventdev/eventdev_pmd.h                   |  41 +++++++
 lib/eventdev/rte_event_eth_tx_adapter.c       | 113 +++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h       |  54 +++++++++
 lib/eventdev/version.map                      |   2 +
 6 files changed, 239 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
index 4da9bcda3a..d1fdf9a6d1 100644
--- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
+++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
@@ -182,3 +182,28 @@ mbufs are destined to the same ethernet port and queue by setting the bit
 ``rte_event_vector::queue``.
 If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
 into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The adapter can be configured to start/stop enqueueing of packets to a NIC
+queue using ``rte_event_eth_tx_adapter_queue_start()`` or
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+These APIs help avoid some unexpected behavior with application stopping ethdev
+Tx queues and adapter being unaware of it. With these APIs, the application can
+call stop API to notify adapter that corresponding ethdev Tx queue is stopped
+and any in-flight packets are freed by adapter dataplane code. Adapter queue
+stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue
+is enabled, application can notify adapter to resume processing of the packets
+for that queue by calling the start API. The ethdev Tx queue is started before
+calling adapter start API.
+
+Start function enables the adapter runtime to start enqueueing packets
+to the Tx queue.
+
+Stop function stops the adapter runtime function from enqueueing any
+packets to the associated Tx queue. This API also frees any packets that
+may have been buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c32c18ff49..ec05ddcbf5 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -30,6 +30,14 @@ New Features
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
 
+
+* **Added Tx adapter queue start/stop API**
+
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from transmitting any
+  packets to the Tx queue.
+
 .. This section should contain new features added in this release.
    Sample format:
 
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index f514a37575..31eaf927df 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 7e82fe030c..5fb6a09f2d 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1319,3 +1347,80 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static inline int
+txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			     bool start_state, struct txa_service_data *txa)
+{
+	struct txa_service_queue_info *tqi = NULL;
+
+	rte_spinlock_lock(&txa->tx_lock);
+	tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+	if (unlikely(tqi == NULL || !tqi->added)) {
+		rte_spinlock_unlock(&txa->tx_lock);
+		return -EINVAL;
+	}
+	if (start_state == false)
+		txa_txq_buffer_drain(tqi);
+
+	tqi->stopped = !start_state;
+	rte_spinlock_unlock(&txa->tx_lock);
+	return 0;
+}
+
+static int
+txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			  bool start_state)
+{
+	struct txa_service_data *txa;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+						    tx_queue_id,
+						    &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						eth_dev_id,
+						&caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+		if (start_state == true) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+			      txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							       eth_dev_id,
+							       tx_queue_id) : 0;
+		} else {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+			      txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							      eth_dev_id,
+							      tx_queue_id) : 0;
+		}
+		return ret;
+	}
+	return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
+					    start_state, txa);
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..4338e73709 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,58 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the Tx adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resume enqueueing packets that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ * @see rte_event_eth_tx_adapter_queue_stop
+ *
+ * Use case:
+ * --------
+ * The queue start/stop APIs help avoid some unexpected behavior with
+ * application stopping ethdev Tx queues and adapter being unaware of it.
+ * With these APIs, the application can call stop API to notify adapter
+ * that corresponding ethdev Tx queue is stopped and any in-flight
+ * packets are freed by adapter dataplane code. Adapter queue stop API
+ * is called before stopping the ethdev Tx queue. When ethdev Tx queue
+ * is enabled, application can notify adapter to resume processing of
+ * the packets for that queue by calling the start API. The ethdev Tx
+ * queue is started before calling adapter start API.
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx adapter runtime function from enqueueing any packets
+ * to the associated Tx queue. This API also frees any packets that may
+ * have been buffered for this queue. All inflight packets destined to the
+ * queue are freed by the adapter runtime until the queue is started again.
+ * @see rte_event_eth_tx_adapter_queue_start
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v5 2/2] test/eth_tx: add testcase for queue start stop APIs
  2022-09-16 16:23     ` [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-16 16:23       ` Naga Harish K S V
  2022-09-26  2:04       ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  1 sibling, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-16 16:23 UTC (permalink / raw)
  To: jerinj, jay.jayatheerthan; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-16 16:23     ` [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-16 16:23       ` [PATCH v5 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
@ 2022-09-26  2:04       ` Naga Harish K S V
  2022-09-26  2:04         ` [PATCH v6 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
  2022-09-27 10:15         ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Jerin Jacob
  1 sibling, 2 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-26  2:04 UTC (permalink / raw)
  To: jay.jayatheerthan, jerinjacobk; +Cc: dev

Add support to start or stop a particular queue
that is associated with the adapter.

Start function enables the Tx adapter to start enqueueing
packets to the Tx queue.

Stop function stops the Tx adapter from enqueueing any
packets to the Tx queue. The stop API also frees any packets
that may have been buffered for this queue. All inflight packets
destined to the queue are freed by the adapter runtime until the
queue is started again.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
v6:
* fix nitpicks
v5:
* fix build failure
v4:
* update programmer guide and doxygen comments
v3:
* fix documentation and address review comments
---
---
 .../prog_guide/event_ethernet_tx_adapter.rst  |  25 ++++
 doc/guides/rel_notes/release_22_11.rst        |   8 ++
 lib/eventdev/eventdev_pmd.h                   |  41 +++++++
 lib/eventdev/rte_event_eth_tx_adapter.c       | 112 +++++++++++++++++-
 lib/eventdev/rte_event_eth_tx_adapter.h       |  54 +++++++++
 lib/eventdev/version.map                      |   2 +
 6 files changed, 238 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
index 1a5b069d60..73022e307a 100644
--- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
+++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
@@ -182,3 +182,28 @@ mbufs are destined to the same ethernet port and queue by setting the bit
 ``rte_event_vector::queue``.
 If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
 into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The adapter can be configured to start/stop enqueueing of packets to a
+associated NIC queue using ``rte_event_eth_tx_adapter_queue_start()`` or
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+These APIs help avoid some unexpected behavior with application stopping ethdev
+Tx queues and adapter being unaware of it. With these APIs, the application can
+call stop API to notify adapter that corresponding ethdev Tx queue is stopped
+and any in-flight packets are freed by adapter dataplane code. Adapter queue
+stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue
+is enabled, application can notify adapter to resume processing of the packets
+for that queue by calling the start API. The ethdev Tx queue is started before
+calling adapter start API.
+
+Start function enables the adapter runtime to start enqueueing of packets
+to the Tx queue.
+
+Stop function stops the adapter runtime function from enqueueing any
+packets to the associated Tx queue. This API also frees any packets that
+may have been buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 97720a78ee..a4a51598a1 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -31,6 +31,14 @@ New Features
   Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
   ethernet device id and Tx queue index.
 
+
+* **Added Tx adapter queue start/stop API**
+
+  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+  Tx adapter.
+  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from enqueueing any
+  packets to the Tx queue.
+
 .. This section should contain new features added in this release.
    Sample format:
 
diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
index 1e65d096f1..27b936a60e 100644
--- a/lib/eventdev/eventdev_pmd.h
+++ b/lib/eventdev/eventdev_pmd.h
@@ -1277,6 +1277,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
 typedef int (*eventdev_eth_tx_adapter_instance_get_t)
 	(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
 
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ *  Adapter identifier
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ *  Ethernet device Tx queue index
+ *
+ * @return
+ *  -  0: Success
+ *  - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+	(uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 /** Event device operations function pointer table */
 struct eventdev_ops {
@@ -1390,6 +1427,10 @@ struct eventdev_ops {
 	/**< Reset eth Tx adapter statistics */
 	eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
 	/**< Get Tx adapter instance id for Tx queue */
+	eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+	/**< Start Tx queue assigned to Tx adapter instance */
+	eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+	/**< Stop Tx queue assigned to Tx adapter instance */
 
 	eventdev_selftest dev_selftest;
 	/**< Start eventdev Selftest */
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 7e82fe030c..8f12762201 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -47,6 +47,12 @@
 #define txa_dev_instance_get(id) \
 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
 
+#define txa_dev_queue_start(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+			txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
 do { \
 	if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
 struct txa_service_queue_info {
 	/* Queue has been added */
 	uint8_t added;
+	/* Queue is stopped */
+	bool stopped;
 	/* Retry callback argument */
 	struct txa_retry txa_retry;
 	/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
 		port = vec->port;
 		queue = vec->queue;
 		tqi = txa_service_queue(txa, port, queue);
-		if (unlikely(tqi == NULL || !tqi->added)) {
+		if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
 			rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
 			return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
 			port = mbufs[i]->port;
 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(mbufs[i]);
 				continue;
 			}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
 			queue = rte_event_eth_tx_adapter_txq_get(m);
 
 			tqi = txa_service_queue(txa, port, queue);
-			if (unlikely(tqi == NULL || !tqi->added)) {
+			if (unlikely(tqi == NULL || !tqi->added ||
+				     tqi->stopped)) {
 				rte_pktmbuf_free(m);
 				continue;
 			}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
 
 				tqi = txa_service_queue(txa, i, q);
-				if (unlikely(tqi == NULL || !tqi->added))
+				if (unlikely(tqi == NULL || !tqi->added ||
+					     tqi->stopped))
 					continue;
 
 				nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
 
 	tqi->tx_buf = tb;
 	tqi->added = 1;
+	tqi->stopped = false;
 	tdi->nb_queues++;
 	txa->nb_queues++;
 
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
 	return -1;
 }
 
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+	struct rte_eth_dev_tx_buffer *b;
+	uint16_t i;
+
+	b = tqi->tx_buf;
+
+	for (i = 0; i < b->length; i++)
+		rte_pktmbuf_free(b->pkts[i]);
+
+	b->length = 0;
+}
+
 static int
 txa_service_queue_del(uint8_t id,
 		const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
 	if (tqi == NULL || !tqi->added)
 		goto ret_unlock;
 
+	/* Drain the buffered mbufs */
+	txa_txq_buffer_drain(tqi);
 	tb = tqi->tx_buf;
 	tqi->added = 0;
 	tqi->tx_buf = NULL;
@@ -1319,3 +1347,79 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 
 	return -EINVAL;
 }
+
+static inline int
+txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			     bool start_state, struct txa_service_data *txa)
+{
+	struct txa_service_queue_info *tqi = NULL;
+
+	rte_spinlock_lock(&txa->tx_lock);
+	tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+	if (unlikely(tqi == NULL || !tqi->added)) {
+		rte_spinlock_unlock(&txa->tx_lock);
+		return -EINVAL;
+	}
+	if (start_state == false)
+		txa_txq_buffer_drain(tqi);
+
+	tqi->stopped = !start_state;
+	rte_spinlock_unlock(&txa->tx_lock);
+	return 0;
+}
+
+static int
+txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
+			  bool start_state)
+{
+	struct txa_service_data *txa;
+	uint8_t txa_inst_id;
+	int ret;
+	uint32_t caps = 0;
+
+	/* Below API already does validation of input parameters.
+	 * Hence skipping the validation here.
+	 */
+	ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+						    tx_queue_id,
+						    &txa_inst_id);
+	if (ret < 0)
+		return -EINVAL;
+
+	txa = txa_service_id_to_data(txa_inst_id);
+	ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+						eth_dev_id,
+						&caps);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+		if (start_state == true) {
+			ret = txa_dev_queue_start(txa_inst_id) ?
+			      txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+							       eth_dev_id,
+							       tx_queue_id) : 0;
+		} else {
+			ret = txa_dev_queue_stop(txa_inst_id) ?
+			      txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+							      eth_dev_id,
+							      tx_queue_id) : 0;
+		}
+		return ret;
+	}
+
+	return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
+					    start_state, txa);
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+	return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
+}
diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
index 9432b740e8..74ded7b651 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.h
+++ b/lib/eventdev/rte_event_eth_tx_adapter.h
@@ -35,6 +35,8 @@
  *  - rte_event_eth_tx_adapter_event_port_get()
  *  - rte_event_eth_tx_adapter_service_id_get()
  *  - rte_event_eth_tx_adapter_instance_get()
+ *  - rte_event_eth_tx_adapter_queue_start()
+ *  - rte_event_eth_tx_adapter_queue_stop()
  *
  * The application creates the adapter using
  * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,58 @@ int
 rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
 				      uint16_t tx_queue_id,
 				      uint8_t *txa_inst_id);
+/**
+ * Enables the adapter to start enqueueing of packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resume enqueueing packets that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop().
+ * @see rte_event_eth_tx_adapter_queue_stop
+ *
+ * Use case:
+ * --------
+ * The queue start/stop APIs help avoid some unexpected behavior with
+ * application stopping ethdev Tx queues and adapter being unaware of it.
+ * With these APIs, the application can call stop API to notify adapter
+ * that corresponding ethdev Tx queue is stopped and any in-flight
+ * packets are freed by adapter dataplane code. Adapter queue stop API
+ * is called before stopping the ethdev Tx queue. When ethdev Tx queue
+ * is enabled, application can notify adapter to resume processing of
+ * the packets for that queue by calling the start API. The ethdev Tx
+ * queue is started before calling adapter start API.
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the adapter runtime function from enqueueing any packets
+ * to the associated Tx queue. This API also frees any packets that may
+ * have been buffered for this queue. All inflight packets destined to the
+ * queue are freed by the adapter runtime until the queue is started again.
+ * @see rte_event_eth_tx_adapter_queue_start
+ *
+ * @param eth_dev_id
+ *  Port identifier of Ethernet device.
+ * @param tx_queue_id
+ *  Ethernet device transmit queue index.
+ * @return
+ *   - 0: Success
+ *   - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index 9a71cf3f8f..dd63ec6f68 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -116,6 +116,8 @@ EXPERIMENTAL {
 	# added in 22.11
 	rte_event_eth_rx_adapter_instance_get;
 	rte_event_eth_tx_adapter_instance_get;
+	rte_event_eth_tx_adapter_queue_start;
+	rte_event_eth_tx_adapter_queue_stop;
 };
 
 INTERNAL {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v6 2/2] test/eth_tx: add testcase for queue start stop APIs
  2022-09-26  2:04       ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
@ 2022-09-26  2:04         ` Naga Harish K S V
  2022-09-27 10:15         ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Jerin Jacob
  1 sibling, 0 replies; 20+ messages in thread
From: Naga Harish K S V @ 2022-09-26  2:04 UTC (permalink / raw)
  To: jay.jayatheerthan, jerinjacobk; +Cc: dev

Added testcase for rte_event_eth_tx_adapter_queue_start()
and rte_event_eth_tx_adapter_queue_stop() APIs.

Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
---
 app/test/test_event_eth_tx_adapter.c | 86 ++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/app/test/test_event_eth_tx_adapter.c b/app/test/test_event_eth_tx_adapter.c
index 98debfdd2c..c19a87a86a 100644
--- a/app/test/test_event_eth_tx_adapter.c
+++ b/app/test/test_event_eth_tx_adapter.c
@@ -711,6 +711,90 @@ tx_adapter_instance_get(void)
 	return TEST_SUCCESS;
 }
 
+static int
+tx_adapter_queue_start_stop(void)
+{
+	int err;
+	uint16_t eth_dev_id;
+	struct rte_eth_dev_info dev_info;
+
+	/* Case 1: Test without adding eth Tx queue */
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 2: Test with wrong eth port */
+	eth_dev_id = rte_eth_dev_count_total() + 1;
+	err = rte_event_eth_tx_adapter_queue_start(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(eth_dev_id,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 3: Test with wrong tx queue */
+	err = rte_eth_dev_info_get(TEST_ETHDEV_ID, &dev_info);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    dev_info.max_tx_queues + 1);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Case 4: Test with right instance, port & rxq */
+	/* Add queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Add another queue to tx adapter */
+	err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	/* Case 5: Test with right instance, port & wrong rxq */
+	err = rte_event_eth_tx_adapter_queue_stop(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	err = rte_event_eth_tx_adapter_queue_start(TEST_ETHDEV_ID,
+						    TEST_ETH_QUEUE_ID + 2);
+	TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+	/* Delete all queues from the Tx adapter */
+	err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+						 TEST_ETHDEV_ID,
+						 -1);
+	TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+	return TEST_SUCCESS;
+}
+
 static int
 tx_adapter_dynamic_device(void)
 {
@@ -770,6 +854,8 @@ static struct unit_test_suite event_eth_tx_tests = {
 					tx_adapter_service),
 		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
 					tx_adapter_instance_get),
+		TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+					tx_adapter_queue_start_stop),
 		TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-26  2:04       ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
  2022-09-26  2:04         ` [PATCH v6 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
@ 2022-09-27 10:15         ` Jerin Jacob
  2022-09-27 10:28           ` Jayatheerthan, Jay
  1 sibling, 1 reply; 20+ messages in thread
From: Jerin Jacob @ 2022-09-27 10:15 UTC (permalink / raw)
  To: Naga Harish K S V; +Cc: jay.jayatheerthan, dev

On Mon, Sep 26, 2022 at 7:34 AM Naga Harish K S V
<s.v.naga.harish.k@intel.com> wrote:
>
> Add support to start or stop a particular queue
> that is associated with the adapter.
>
> Start function enables the Tx adapter to start enqueueing
> packets to the Tx queue.
>
> Stop function stops the Tx adapter from enqueueing any
> packets to the Tx queue. The stop API also frees any packets
> that may have been buffered for this queue. All inflight packets
> destined to the queue are freed by the adapter runtime until the
> queue is started again.
>
> Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>

I will wait for @Jayatheerthan, Jay Ack to merge to RC1.

> ---
> v6:
> * fix nitpicks
> v5:
> * fix build failure
> v4:
> * update programmer guide and doxygen comments
> v3:
> * fix documentation and address review comments
> ---
> ---
>  .../prog_guide/event_ethernet_tx_adapter.rst  |  25 ++++
>  doc/guides/rel_notes/release_22_11.rst        |   8 ++
>  lib/eventdev/eventdev_pmd.h                   |  41 +++++++
>  lib/eventdev/rte_event_eth_tx_adapter.c       | 112 +++++++++++++++++-
>  lib/eventdev/rte_event_eth_tx_adapter.h       |  54 +++++++++
>  lib/eventdev/version.map                      |   2 +
>  6 files changed, 238 insertions(+), 4 deletions(-)
>
> diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> index 1a5b069d60..73022e307a 100644
> --- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> +++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> @@ -182,3 +182,28 @@ mbufs are destined to the same ethernet port and queue by setting the bit
>  ``rte_event_vector::queue``.
>  If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
>  into each mbuf and transmit them to the requested ethernet port and queue pair.
> +
> +Queue start/stop
> +~~~~~~~~~~~~~~~~
> +
> +The adapter can be configured to start/stop enqueueing of packets to a
> +associated NIC queue using ``rte_event_eth_tx_adapter_queue_start()`` or
> +``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
> +is in start state.
> +
> +These APIs help avoid some unexpected behavior with application stopping ethdev
> +Tx queues and adapter being unaware of it. With these APIs, the application can
> +call stop API to notify adapter that corresponding ethdev Tx queue is stopped
> +and any in-flight packets are freed by adapter dataplane code. Adapter queue
> +stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue
> +is enabled, application can notify adapter to resume processing of the packets
> +for that queue by calling the start API. The ethdev Tx queue is started before
> +calling adapter start API.
> +
> +Start function enables the adapter runtime to start enqueueing of packets
> +to the Tx queue.
> +
> +Stop function stops the adapter runtime function from enqueueing any
> +packets to the associated Tx queue. This API also frees any packets that
> +may have been buffered for this queue. All inflight packets destined to the
> +queue are freed by the adapter runtime until the queue is started again.
> diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
> index 97720a78ee..a4a51598a1 100644
> --- a/doc/guides/rel_notes/release_22_11.rst
> +++ b/doc/guides/rel_notes/release_22_11.rst
> @@ -31,6 +31,14 @@ New Features
>    Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
>    ethernet device id and Tx queue index.
>
> +
> +* **Added Tx adapter queue start/stop API**
> +
> +  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
> +  Tx adapter.
> +  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from enqueueing any
> +  packets to the Tx queue.
> +
>  .. This section should contain new features added in this release.
>     Sample format:
>
> diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
> index 1e65d096f1..27b936a60e 100644
> --- a/lib/eventdev/eventdev_pmd.h
> +++ b/lib/eventdev/eventdev_pmd.h
> @@ -1277,6 +1277,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
>  typedef int (*eventdev_eth_tx_adapter_instance_get_t)
>         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
>
> +/**
> + * Start a Tx queue that is assigned to Tx adapter instance
> + *
> + * @param id
> + *  Adapter identifier
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device
> + *
> + * @param tx_queue_id
> + *  Ethernet device Tx queue index
> + *
> + * @return
> + *  -  0: Success
> + *  - <0: Error code on failure
> + */
> +typedef int (*eventdev_eth_tx_adapter_queue_start)
> +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> +
> +/**
> + * Stop a Tx queue that is assigned to Tx adapter instance
> + *
> + * @param id
> + *  Adapter identifier
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device
> + *
> + * @param tx_queue_id
> + *  Ethernet device Tx queue index
> + *
> + * @return
> + *  -  0: Success
> + *  - <0: Error code on failure
> + */
> +typedef int (*eventdev_eth_tx_adapter_queue_stop)
> +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
>
>  /** Event device operations function pointer table */
>  struct eventdev_ops {
> @@ -1390,6 +1427,10 @@ struct eventdev_ops {
>         /**< Reset eth Tx adapter statistics */
>         eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
>         /**< Get Tx adapter instance id for Tx queue */
> +       eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
> +       /**< Start Tx queue assigned to Tx adapter instance */
> +       eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
> +       /**< Stop Tx queue assigned to Tx adapter instance */
>
>         eventdev_selftest dev_selftest;
>         /**< Start eventdev Selftest */
> diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
> index 7e82fe030c..8f12762201 100644
> --- a/lib/eventdev/rte_event_eth_tx_adapter.c
> +++ b/lib/eventdev/rte_event_eth_tx_adapter.c
> @@ -47,6 +47,12 @@
>  #define txa_dev_instance_get(id) \
>                         txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
>
> +#define txa_dev_queue_start(id) \
> +                       txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
> +
> +#define txa_dev_queue_stop(id) \
> +                       txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
> +
>  #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
>  do { \
>         if (!txa_valid_id(id)) { \
> @@ -94,6 +100,8 @@ struct txa_retry {
>  struct txa_service_queue_info {
>         /* Queue has been added */
>         uint8_t added;
> +       /* Queue is stopped */
> +       bool stopped;
>         /* Retry callback argument */
>         struct txa_retry txa_retry;
>         /* Tx buffer */
> @@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
>                 port = vec->port;
>                 queue = vec->queue;
>                 tqi = txa_service_queue(txa, port, queue);
> -               if (unlikely(tqi == NULL || !tqi->added)) {
> +               if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
>                         rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
>                         rte_mempool_put(rte_mempool_from_obj(vec), vec);
>                         return 0;
> @@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
>                         port = mbufs[i]->port;
>                         queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
>                         tqi = txa_service_queue(txa, port, queue);
> -                       if (unlikely(tqi == NULL || !tqi->added)) {
> +                       if (unlikely(tqi == NULL || !tqi->added ||
> +                                    tqi->stopped)) {
>                                 rte_pktmbuf_free(mbufs[i]);
>                                 continue;
>                         }
> @@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
>                         queue = rte_event_eth_tx_adapter_txq_get(m);
>
>                         tqi = txa_service_queue(txa, port, queue);
> -                       if (unlikely(tqi == NULL || !tqi->added)) {
> +                       if (unlikely(tqi == NULL || !tqi->added ||
> +                                    tqi->stopped)) {
>                                 rte_pktmbuf_free(m);
>                                 continue;
>                         }
> @@ -671,7 +681,8 @@ txa_service_func(void *args)
>                         for (q = 0; q < dev->data->nb_tx_queues; q++) {
>
>                                 tqi = txa_service_queue(txa, i, q);
> -                               if (unlikely(tqi == NULL || !tqi->added))
> +                               if (unlikely(tqi == NULL || !tqi->added ||
> +                                            tqi->stopped))
>                                         continue;
>
>                                 nb_tx += rte_eth_tx_buffer_flush(i, q,
> @@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
>
>         tqi->tx_buf = tb;
>         tqi->added = 1;
> +       tqi->stopped = false;
>         tdi->nb_queues++;
>         txa->nb_queues++;
>
> @@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
>         return -1;
>  }
>
> +static inline void
> +txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
> +{
> +       struct rte_eth_dev_tx_buffer *b;
> +       uint16_t i;
> +
> +       b = tqi->tx_buf;
> +
> +       for (i = 0; i < b->length; i++)
> +               rte_pktmbuf_free(b->pkts[i]);
> +
> +       b->length = 0;
> +}
> +
>  static int
>  txa_service_queue_del(uint8_t id,
>                 const struct rte_eth_dev *dev,
> @@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
>         if (tqi == NULL || !tqi->added)
>                 goto ret_unlock;
>
> +       /* Drain the buffered mbufs */
> +       txa_txq_buffer_drain(tqi);
>         tb = tqi->tx_buf;
>         tqi->added = 0;
>         tqi->tx_buf = NULL;
> @@ -1319,3 +1347,79 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
>
>         return -EINVAL;
>  }
> +
> +static inline int
> +txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
> +                            bool start_state, struct txa_service_data *txa)
> +{
> +       struct txa_service_queue_info *tqi = NULL;
> +
> +       rte_spinlock_lock(&txa->tx_lock);
> +       tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
> +       if (unlikely(tqi == NULL || !tqi->added)) {
> +               rte_spinlock_unlock(&txa->tx_lock);
> +               return -EINVAL;
> +       }
> +       if (start_state == false)
> +               txa_txq_buffer_drain(tqi);
> +
> +       tqi->stopped = !start_state;
> +       rte_spinlock_unlock(&txa->tx_lock);
> +       return 0;
> +}
> +
> +static int
> +txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
> +                         bool start_state)
> +{
> +       struct txa_service_data *txa;
> +       uint8_t txa_inst_id;
> +       int ret;
> +       uint32_t caps = 0;
> +
> +       /* Below API already does validation of input parameters.
> +        * Hence skipping the validation here.
> +        */
> +       ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
> +                                                   tx_queue_id,
> +                                                   &txa_inst_id);
> +       if (ret < 0)
> +               return -EINVAL;
> +
> +       txa = txa_service_id_to_data(txa_inst_id);
> +       ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
> +                                               eth_dev_id,
> +                                               &caps);
> +       if (ret < 0)
> +               return -EINVAL;
> +
> +       if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
> +               if (start_state == true) {
> +                       ret = txa_dev_queue_start(txa_inst_id) ?
> +                             txa_dev_queue_start(txa_inst_id)(txa_inst_id,
> +                                                              eth_dev_id,
> +                                                              tx_queue_id) : 0;
> +               } else {
> +                       ret = txa_dev_queue_stop(txa_inst_id) ?
> +                             txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
> +                                                             eth_dev_id,
> +                                                             tx_queue_id) : 0;
> +               }
> +               return ret;
> +       }
> +
> +       return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
> +                                           start_state, txa);
> +}
> +
> +int
> +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
> +{
> +       return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
> +}
> +
> +int
> +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
> +{
> +       return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
> +}
> diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
> index 9432b740e8..74ded7b651 100644
> --- a/lib/eventdev/rte_event_eth_tx_adapter.h
> +++ b/lib/eventdev/rte_event_eth_tx_adapter.h
> @@ -35,6 +35,8 @@
>   *  - rte_event_eth_tx_adapter_event_port_get()
>   *  - rte_event_eth_tx_adapter_service_id_get()
>   *  - rte_event_eth_tx_adapter_instance_get()
> + *  - rte_event_eth_tx_adapter_queue_start()
> + *  - rte_event_eth_tx_adapter_queue_stop()
>   *
>   * The application creates the adapter using
>   * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
> @@ -446,6 +448,58 @@ int
>  rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
>                                       uint16_t tx_queue_id,
>                                       uint8_t *txa_inst_id);
> +/**
> + * Enables the adapter to start enqueueing of packets to the
> + * Tx queue.
> + *
> + * This function is provided so that the application can
> + * resume enqueueing packets that reference packets for
> + * <eth_dev_id, tx_queue_id> after calling
> + * rte_event_eth_tx_adapter_queue_stop().
> + * @see rte_event_eth_tx_adapter_queue_stop
> + *
> + * Use case:
> + * --------
> + * The queue start/stop APIs help avoid some unexpected behavior with
> + * application stopping ethdev Tx queues and adapter being unaware of it.
> + * With these APIs, the application can call stop API to notify adapter
> + * that corresponding ethdev Tx queue is stopped and any in-flight
> + * packets are freed by adapter dataplane code. Adapter queue stop API
> + * is called before stopping the ethdev Tx queue. When ethdev Tx queue
> + * is enabled, application can notify adapter to resume processing of
> + * the packets for that queue by calling the start API. The ethdev Tx
> + * queue is started before calling adapter start API.
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device.
> + * @param tx_queue_id
> + *  Ethernet device transmit queue index.
> + * @return
> + *   - 0: Success
> + *   - <0: Error code on failure
> + */
> +__rte_experimental
> +int
> +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
> +
> +/**
> + * Stops the adapter runtime function from enqueueing any packets
> + * to the associated Tx queue. This API also frees any packets that may
> + * have been buffered for this queue. All inflight packets destined to the
> + * queue are freed by the adapter runtime until the queue is started again.
> + * @see rte_event_eth_tx_adapter_queue_start
> + *
> + * @param eth_dev_id
> + *  Port identifier of Ethernet device.
> + * @param tx_queue_id
> + *  Ethernet device transmit queue index.
> + * @return
> + *   - 0: Success
> + *   - <0: Error code on failure
> + */
> +__rte_experimental
> +int
> +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
>
>  #ifdef __cplusplus
>  }
> diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
> index 9a71cf3f8f..dd63ec6f68 100644
> --- a/lib/eventdev/version.map
> +++ b/lib/eventdev/version.map
> @@ -116,6 +116,8 @@ EXPERIMENTAL {
>         # added in 22.11
>         rte_event_eth_rx_adapter_instance_get;
>         rte_event_eth_tx_adapter_instance_get;
> +       rte_event_eth_tx_adapter_queue_start;
> +       rte_event_eth_tx_adapter_queue_stop;
>  };
>
>  INTERNAL {
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-27 10:15         ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Jerin Jacob
@ 2022-09-27 10:28           ` Jayatheerthan, Jay
  2022-09-28  3:46             ` Jerin Jacob
  0 siblings, 1 reply; 20+ messages in thread
From: Jayatheerthan, Jay @ 2022-09-27 10:28 UTC (permalink / raw)
  To: Jerin Jacob, Naga Harish K, S V; +Cc: dev

> -----Original Message-----
> From: Jerin Jacob <jerinjacobk@gmail.com>
> Sent: Tuesday, September 27, 2022 3:45 PM
> To: Naga Harish K, S V <s.v.naga.harish.k@intel.com>
> Cc: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>; dev@dpdk.org
> Subject: Re: [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
> 
> On Mon, Sep 26, 2022 at 7:34 AM Naga Harish K S V
> <s.v.naga.harish.k@intel.com> wrote:
> >
> > Add support to start or stop a particular queue
> > that is associated with the adapter.
> >
> > Start function enables the Tx adapter to start enqueueing
> > packets to the Tx queue.
> >
> > Stop function stops the Tx adapter from enqueueing any
> > packets to the Tx queue. The stop API also frees any packets
> > that may have been buffered for this queue. All inflight packets
> > destined to the queue are freed by the adapter runtime until the
> > queue is started again.
> >
> > Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
> 
> I will wait for @Jayatheerthan, Jay Ack to merge to RC1.

The full patchset looks good to me. Thanks for adding useful set of APIs.

Acked-by: Jay Jayatheerthan <jay.jayatheerthan@intel.com>

> 
> > ---
> > v6:
> > * fix nitpicks
> > v5:
> > * fix build failure
> > v4:
> > * update programmer guide and doxygen comments
> > v3:
> > * fix documentation and address review comments
> > ---
> > ---
> >  .../prog_guide/event_ethernet_tx_adapter.rst  |  25 ++++
> >  doc/guides/rel_notes/release_22_11.rst        |   8 ++
> >  lib/eventdev/eventdev_pmd.h                   |  41 +++++++
> >  lib/eventdev/rte_event_eth_tx_adapter.c       | 112 +++++++++++++++++-
> >  lib/eventdev/rte_event_eth_tx_adapter.h       |  54 +++++++++
> >  lib/eventdev/version.map                      |   2 +
> >  6 files changed, 238 insertions(+), 4 deletions(-)
> >
> > diff --git a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> > index 1a5b069d60..73022e307a 100644
> > --- a/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> > +++ b/doc/guides/prog_guide/event_ethernet_tx_adapter.rst
> > @@ -182,3 +182,28 @@ mbufs are destined to the same ethernet port and queue by setting the bit
> >  ``rte_event_vector::queue``.
> >  If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
> >  into each mbuf and transmit them to the requested ethernet port and queue pair.
> > +
> > +Queue start/stop
> > +~~~~~~~~~~~~~~~~
> > +
> > +The adapter can be configured to start/stop enqueueing of packets to a
> > +associated NIC queue using ``rte_event_eth_tx_adapter_queue_start()`` or
> > +``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
> > +is in start state.
> > +
> > +These APIs help avoid some unexpected behavior with application stopping ethdev
> > +Tx queues and adapter being unaware of it. With these APIs, the application can
> > +call stop API to notify adapter that corresponding ethdev Tx queue is stopped
> > +and any in-flight packets are freed by adapter dataplane code. Adapter queue
> > +stop API is called before stopping the ethdev Tx queue. When ethdev Tx queue
> > +is enabled, application can notify adapter to resume processing of the packets
> > +for that queue by calling the start API. The ethdev Tx queue is started before
> > +calling adapter start API.
> > +
> > +Start function enables the adapter runtime to start enqueueing of packets
> > +to the Tx queue.
> > +
> > +Stop function stops the adapter runtime function from enqueueing any
> > +packets to the associated Tx queue. This API also frees any packets that
> > +may have been buffered for this queue. All inflight packets destined to the
> > +queue are freed by the adapter runtime until the queue is started again.
> > diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
> > index 97720a78ee..a4a51598a1 100644
> > --- a/doc/guides/rel_notes/release_22_11.rst
> > +++ b/doc/guides/rel_notes/release_22_11.rst
> > @@ -31,6 +31,14 @@ New Features
> >    Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
> >    ethernet device id and Tx queue index.
> >
> > +
> > +* **Added Tx adapter queue start/stop API**
> > +
> > +  Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
> > +  Tx adapter.
> > +  Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from enqueueing any
> > +  packets to the Tx queue.
> > +
> >  .. This section should contain new features added in this release.
> >     Sample format:
> >
> > diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h
> > index 1e65d096f1..27b936a60e 100644
> > --- a/lib/eventdev/eventdev_pmd.h
> > +++ b/lib/eventdev/eventdev_pmd.h
> > @@ -1277,6 +1277,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
> >  typedef int (*eventdev_eth_tx_adapter_instance_get_t)
> >         (uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
> >
> > +/**
> > + * Start a Tx queue that is assigned to Tx adapter instance
> > + *
> > + * @param id
> > + *  Adapter identifier
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device
> > + *
> > + * @param tx_queue_id
> > + *  Ethernet device Tx queue index
> > + *
> > + * @return
> > + *  -  0: Success
> > + *  - <0: Error code on failure
> > + */
> > +typedef int (*eventdev_eth_tx_adapter_queue_start)
> > +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> > +
> > +/**
> > + * Stop a Tx queue that is assigned to Tx adapter instance
> > + *
> > + * @param id
> > + *  Adapter identifier
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device
> > + *
> > + * @param tx_queue_id
> > + *  Ethernet device Tx queue index
> > + *
> > + * @return
> > + *  -  0: Success
> > + *  - <0: Error code on failure
> > + */
> > +typedef int (*eventdev_eth_tx_adapter_queue_stop)
> > +       (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
> >
> >  /** Event device operations function pointer table */
> >  struct eventdev_ops {
> > @@ -1390,6 +1427,10 @@ struct eventdev_ops {
> >         /**< Reset eth Tx adapter statistics */
> >         eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
> >         /**< Get Tx adapter instance id for Tx queue */
> > +       eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
> > +       /**< Start Tx queue assigned to Tx adapter instance */
> > +       eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
> > +       /**< Stop Tx queue assigned to Tx adapter instance */
> >
> >         eventdev_selftest dev_selftest;
> >         /**< Start eventdev Selftest */
> > diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
> > index 7e82fe030c..8f12762201 100644
> > --- a/lib/eventdev/rte_event_eth_tx_adapter.c
> > +++ b/lib/eventdev/rte_event_eth_tx_adapter.c
> > @@ -47,6 +47,12 @@
> >  #define txa_dev_instance_get(id) \
> >                         txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
> >
> > +#define txa_dev_queue_start(id) \
> > +                       txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
> > +
> > +#define txa_dev_queue_stop(id) \
> > +                       txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
> > +
> >  #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
> >  do { \
> >         if (!txa_valid_id(id)) { \
> > @@ -94,6 +100,8 @@ struct txa_retry {
> >  struct txa_service_queue_info {
> >         /* Queue has been added */
> >         uint8_t added;
> > +       /* Queue is stopped */
> > +       bool stopped;
> >         /* Retry callback argument */
> >         struct txa_retry txa_retry;
> >         /* Tx buffer */
> > @@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
> >                 port = vec->port;
> >                 queue = vec->queue;
> >                 tqi = txa_service_queue(txa, port, queue);
> > -               if (unlikely(tqi == NULL || !tqi->added)) {
> > +               if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
> >                         rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
> >                         rte_mempool_put(rte_mempool_from_obj(vec), vec);
> >                         return 0;
> > @@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
> >                         port = mbufs[i]->port;
> >                         queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
> >                         tqi = txa_service_queue(txa, port, queue);
> > -                       if (unlikely(tqi == NULL || !tqi->added)) {
> > +                       if (unlikely(tqi == NULL || !tqi->added ||
> > +                                    tqi->stopped)) {
> >                                 rte_pktmbuf_free(mbufs[i]);
> >                                 continue;
> >                         }
> > @@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
> >                         queue = rte_event_eth_tx_adapter_txq_get(m);
> >
> >                         tqi = txa_service_queue(txa, port, queue);
> > -                       if (unlikely(tqi == NULL || !tqi->added)) {
> > +                       if (unlikely(tqi == NULL || !tqi->added ||
> > +                                    tqi->stopped)) {
> >                                 rte_pktmbuf_free(m);
> >                                 continue;
> >                         }
> > @@ -671,7 +681,8 @@ txa_service_func(void *args)
> >                         for (q = 0; q < dev->data->nb_tx_queues; q++) {
> >
> >                                 tqi = txa_service_queue(txa, i, q);
> > -                               if (unlikely(tqi == NULL || !tqi->added))
> > +                               if (unlikely(tqi == NULL || !tqi->added ||
> > +                                            tqi->stopped))
> >                                         continue;
> >
> >                                 nb_tx += rte_eth_tx_buffer_flush(i, q,
> > @@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
> >
> >         tqi->tx_buf = tb;
> >         tqi->added = 1;
> > +       tqi->stopped = false;
> >         tdi->nb_queues++;
> >         txa->nb_queues++;
> >
> > @@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
> >         return -1;
> >  }
> >
> > +static inline void
> > +txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
> > +{
> > +       struct rte_eth_dev_tx_buffer *b;
> > +       uint16_t i;
> > +
> > +       b = tqi->tx_buf;
> > +
> > +       for (i = 0; i < b->length; i++)
> > +               rte_pktmbuf_free(b->pkts[i]);
> > +
> > +       b->length = 0;
> > +}
> > +
> >  static int
> >  txa_service_queue_del(uint8_t id,
> >                 const struct rte_eth_dev *dev,
> > @@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
> >         if (tqi == NULL || !tqi->added)
> >                 goto ret_unlock;
> >
> > +       /* Drain the buffered mbufs */
> > +       txa_txq_buffer_drain(tqi);
> >         tb = tqi->tx_buf;
> >         tqi->added = 0;
> >         tqi->tx_buf = NULL;
> > @@ -1319,3 +1347,79 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
> >
> >         return -EINVAL;
> >  }
> > +
> > +static inline int
> > +txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
> > +                            bool start_state, struct txa_service_data *txa)
> > +{
> > +       struct txa_service_queue_info *tqi = NULL;
> > +
> > +       rte_spinlock_lock(&txa->tx_lock);
> > +       tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
> > +       if (unlikely(tqi == NULL || !tqi->added)) {
> > +               rte_spinlock_unlock(&txa->tx_lock);
> > +               return -EINVAL;
> > +       }
> > +       if (start_state == false)
> > +               txa_txq_buffer_drain(tqi);
> > +
> > +       tqi->stopped = !start_state;
> > +       rte_spinlock_unlock(&txa->tx_lock);
> > +       return 0;
> > +}
> > +
> > +static int
> > +txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
> > +                         bool start_state)
> > +{
> > +       struct txa_service_data *txa;
> > +       uint8_t txa_inst_id;
> > +       int ret;
> > +       uint32_t caps = 0;
> > +
> > +       /* Below API already does validation of input parameters.
> > +        * Hence skipping the validation here.
> > +        */
> > +       ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
> > +                                                   tx_queue_id,
> > +                                                   &txa_inst_id);
> > +       if (ret < 0)
> > +               return -EINVAL;
> > +
> > +       txa = txa_service_id_to_data(txa_inst_id);
> > +       ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
> > +                                               eth_dev_id,
> > +                                               &caps);
> > +       if (ret < 0)
> > +               return -EINVAL;
> > +
> > +       if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
> > +               if (start_state == true) {
> > +                       ret = txa_dev_queue_start(txa_inst_id) ?
> > +                             txa_dev_queue_start(txa_inst_id)(txa_inst_id,
> > +                                                              eth_dev_id,
> > +                                                              tx_queue_id) : 0;
> > +               } else {
> > +                       ret = txa_dev_queue_stop(txa_inst_id) ?
> > +                             txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
> > +                                                             eth_dev_id,
> > +                                                             tx_queue_id) : 0;
> > +               }
> > +               return ret;
> > +       }
> > +
> > +       return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
> > +                                           start_state, txa);
> > +}
> > +
> > +int
> > +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
> > +{
> > +       return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
> > +}
> > +
> > +int
> > +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
> > +{
> > +       return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
> > +}
> > diff --git a/lib/eventdev/rte_event_eth_tx_adapter.h b/lib/eventdev/rte_event_eth_tx_adapter.h
> > index 9432b740e8..74ded7b651 100644
> > --- a/lib/eventdev/rte_event_eth_tx_adapter.h
> > +++ b/lib/eventdev/rte_event_eth_tx_adapter.h
> > @@ -35,6 +35,8 @@
> >   *  - rte_event_eth_tx_adapter_event_port_get()
> >   *  - rte_event_eth_tx_adapter_service_id_get()
> >   *  - rte_event_eth_tx_adapter_instance_get()
> > + *  - rte_event_eth_tx_adapter_queue_start()
> > + *  - rte_event_eth_tx_adapter_queue_stop()
> >   *
> >   * The application creates the adapter using
> >   * rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
> > @@ -446,6 +448,58 @@ int
> >  rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
> >                                       uint16_t tx_queue_id,
> >                                       uint8_t *txa_inst_id);
> > +/**
> > + * Enables the adapter to start enqueueing of packets to the
> > + * Tx queue.
> > + *
> > + * This function is provided so that the application can
> > + * resume enqueueing packets that reference packets for
> > + * <eth_dev_id, tx_queue_id> after calling
> > + * rte_event_eth_tx_adapter_queue_stop().
> > + * @see rte_event_eth_tx_adapter_queue_stop
> > + *
> > + * Use case:
> > + * --------
> > + * The queue start/stop APIs help avoid some unexpected behavior with
> > + * application stopping ethdev Tx queues and adapter being unaware of it.
> > + * With these APIs, the application can call stop API to notify adapter
> > + * that corresponding ethdev Tx queue is stopped and any in-flight
> > + * packets are freed by adapter dataplane code. Adapter queue stop API
> > + * is called before stopping the ethdev Tx queue. When ethdev Tx queue
> > + * is enabled, application can notify adapter to resume processing of
> > + * the packets for that queue by calling the start API. The ethdev Tx
> > + * queue is started before calling adapter start API.
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device.
> > + * @param tx_queue_id
> > + *  Ethernet device transmit queue index.
> > + * @return
> > + *   - 0: Success
> > + *   - <0: Error code on failure
> > + */
> > +__rte_experimental
> > +int
> > +rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
> > +
> > +/**
> > + * Stops the adapter runtime function from enqueueing any packets
> > + * to the associated Tx queue. This API also frees any packets that may
> > + * have been buffered for this queue. All inflight packets destined to the
> > + * queue are freed by the adapter runtime until the queue is started again.
> > + * @see rte_event_eth_tx_adapter_queue_start
> > + *
> > + * @param eth_dev_id
> > + *  Port identifier of Ethernet device.
> > + * @param tx_queue_id
> > + *  Ethernet device transmit queue index.
> > + * @return
> > + *   - 0: Success
> > + *   - <0: Error code on failure
> > + */
> > +__rte_experimental
> > +int
> > +rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
> >
> >  #ifdef __cplusplus
> >  }
> > diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
> > index 9a71cf3f8f..dd63ec6f68 100644
> > --- a/lib/eventdev/version.map
> > +++ b/lib/eventdev/version.map
> > @@ -116,6 +116,8 @@ EXPERIMENTAL {
> >         # added in 22.11
> >         rte_event_eth_rx_adapter_instance_get;
> >         rte_event_eth_tx_adapter_instance_get;
> > +       rte_event_eth_tx_adapter_queue_start;
> > +       rte_event_eth_tx_adapter_queue_stop;
> >  };
> >
> >  INTERNAL {
> > --
> > 2.25.1
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
  2022-09-27 10:28           ` Jayatheerthan, Jay
@ 2022-09-28  3:46             ` Jerin Jacob
  0 siblings, 0 replies; 20+ messages in thread
From: Jerin Jacob @ 2022-09-28  3:46 UTC (permalink / raw)
  To: Jayatheerthan, Jay; +Cc: Naga Harish K, S V, dev

On Tue, Sep 27, 2022 at 3:59 PM Jayatheerthan, Jay
<jay.jayatheerthan@intel.com> wrote:
>
> > -----Original Message-----
> > From: Jerin Jacob <jerinjacobk@gmail.com>
> > Sent: Tuesday, September 27, 2022 3:45 PM
> > To: Naga Harish K, S V <s.v.naga.harish.k@intel.com>
> > Cc: Jayatheerthan, Jay <jay.jayatheerthan@intel.com>; dev@dpdk.org
> > Subject: Re: [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API
> >
> > On Mon, Sep 26, 2022 at 7:34 AM Naga Harish K S V
> > <s.v.naga.harish.k@intel.com> wrote:
> > >
> > > Add support to start or stop a particular queue
> > > that is associated with the adapter.
> > >
> > > Start function enables the Tx adapter to start enqueueing
> > > packets to the Tx queue.
> > >
> > > Stop function stops the Tx adapter from enqueueing any
> > > packets to the Tx queue. The stop API also frees any packets
> > > that may have been buffered for this queue. All inflight packets
> > > destined to the queue are freed by the adapter runtime until the
> > > queue is started again.
> > >
> > > Signed-off-by: Naga Harish K S V <s.v.naga.harish.k@intel.com>
> >
> > I will wait for @Jayatheerthan, Jay Ack to merge to RC1.
>
> The full patchset looks good to me. Thanks for adding useful set of APIs.
>
> Acked-by: Jay Jayatheerthan <jay.jayatheerthan@intel.com>

Series applied to dpdk-next-net-eventdev/for-main. Thanks

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-09-28  3:46 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-09  3:42 [PATCH 1/3] eventdev/eth_tx: add queue start stop API Naga Harish K S V
2022-09-09  3:42 ` [PATCH 2/3] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-09  3:42 ` [PATCH 3/3] doc: added eth Tx adapter " Naga Harish K S V
2022-09-14 15:20 ` [PATCH 1/3] eventdev/eth_tx: add queue start stop API Jerin Jacob
2022-09-16  5:21   ` Naga Harish K, S V
2022-09-16  6:10   ` Jayatheerthan, Jay
2022-09-16 15:18     ` Naga Harish K, S V
2022-09-15  9:53 ` [PATCH v2 1/2] " Naga Harish K S V
2022-09-15  9:53   ` [PATCH v2 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-15 15:19   ` [PATCH v3 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
2022-09-15 15:19     ` [PATCH v3 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-16 15:15     ` [PATCH v4 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
2022-09-16 15:15       ` [PATCH v4 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-16 16:23     ` [PATCH v5 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
2022-09-16 16:23       ` [PATCH v5 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-26  2:04       ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Naga Harish K S V
2022-09-26  2:04         ` [PATCH v6 2/2] test/eth_tx: add testcase for queue start stop APIs Naga Harish K S V
2022-09-27 10:15         ` [PATCH v6 1/2] eventdev/eth_tx: add queue start stop API Jerin Jacob
2022-09-27 10:28           ` Jayatheerthan, Jay
2022-09-28  3:46             ` Jerin Jacob

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).