net/mlx5: fix completion queue overflow for large bursts

Message ID 1564926927-31450-1-git-send-email-viacheslavo@mellanox.com (mailing list archive)
State Changes Requested, archived
Delegated to: Raslan Darawsheh
Headers
Series net/mlx5: fix completion queue overflow for large bursts |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Slava Ovsiienko Aug. 4, 2019, 1:55 p.m. UTC
  There is the limit on completion descriptor fetch to improve
latency. If burst size is large there might be not enough
resources freed in completion processing. This fix reiterates
sending loop and allows multiple completion descriptor fetch
and processing.

Fixes: 18a1c20044c0 ("net/mlx5: implement Tx burst template")

Signed-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 29 ++++++++++++++++++++---------
 drivers/net/mlx5/mlx5_rxtx.h |  1 +
 2 files changed, 21 insertions(+), 9 deletions(-)
  

Comments

Matan Azrad Aug. 5, 2019, 6:40 a.m. UTC | #1
From: Viacheslav Ovsiienko
> There is the limit on completion descriptor fetch to improve latency. If burst
> size is large there might be not enough resources freed in completion
> processing. This fix reiterates sending loop and allows multiple completion
> descriptor fetch and processing.
> 
> Fixes: 18a1c20044c0 ("net/mlx5: implement Tx burst template")
> 
> Signed-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
Acked-by: Matan Azrad <matan@mellanox.com>
  

Patch

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 308133b..4b26562 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -4522,6 +4522,14 @@  enum mlx5_txcmp_code {
 
 	assert(txq->elts_s >= (uint16_t)(txq->elts_head - txq->elts_tail));
 	assert(txq->wqe_s >= (uint16_t)(txq->wqe_ci - txq->wqe_pi));
+	if (unlikely(!pkts_n))
+		return 0;
+	loc.pkts_sent = 0;
+	loc.pkts_copy = 0;
+	loc.wqe_last = NULL;
+
+send_loop:
+	loc.pkts_loop = loc.pkts_sent;
 	/*
 	 * Check if there are some CQEs, if any:
 	 * - process an encountered errors
@@ -4529,9 +4537,7 @@  enum mlx5_txcmp_code {
 	 * - free related mbufs
 	 * - doorbell the NIC about processed CQEs
 	 */
-	if (unlikely(!pkts_n))
-		return 0;
-	rte_prefetch0(*pkts);
+	rte_prefetch0(*(pkts + loc.pkts_sent));
 	mlx5_tx_handle_completion(txq, olx);
 	/*
 	 * Calculate the number of available resources - elts and WQEs.
@@ -4548,10 +4554,7 @@  enum mlx5_txcmp_code {
 	loc.wqe_free = txq->wqe_s -
 				(uint16_t)(txq->wqe_ci - txq->wqe_pi);
 	if (unlikely(!loc.elts_free || !loc.wqe_free))
-		return 0;
-	loc.pkts_sent = 0;
-	loc.pkts_copy = 0;
-	loc.wqe_last = NULL;
+		return loc.pkts_sent;
 	for (;;) {
 		/*
 		 * Fetch the packet from array. Usually this is
@@ -4717,8 +4720,8 @@  enum mlx5_txcmp_code {
 	 */
 	assert(MLX5_TXOFF_CONFIG(INLINE) || loc.pkts_sent >= loc.pkts_copy);
 	/* Take a shortcut if nothing is sent. */
-	if (unlikely(loc.pkts_sent == 0))
-		return 0;
+	if (unlikely(loc.pkts_sent == loc.pkts_loop))
+		return loc.pkts_sent;
 	/*
 	 * Ring QP doorbell immediately after WQE building completion
 	 * to improve latencies. The pure software related data treatment
@@ -4747,6 +4750,14 @@  enum mlx5_txcmp_code {
 #endif
 	assert(txq->elts_s >= (uint16_t)(txq->elts_head - txq->elts_tail));
 	assert(txq->wqe_s >= (uint16_t)(txq->wqe_ci - txq->wqe_pi));
+	if (pkts_n > loc.pkts_sent) {
+		/*
+		 * If burst size is large there might be no enough CQE
+		 * fetched from completion queue and no enough resources
+		 * freed to send all the packets.
+		 */
+		goto send_loop;
+	}
 	return loc.pkts_sent;
 }
 
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index aaa02a2..bad9e9c 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -239,6 +239,7 @@  struct mlx5_txq_local {
 	struct rte_mbuf *mbuf; /* first mbuf to process. */
 	uint16_t pkts_copy; /* packets copied to elts. */
 	uint16_t pkts_sent; /* packets sent. */
+	uint16_t pkts_loop; /* packets sent on loop entry. */
 	uint16_t elts_free; /* available elts remain. */
 	uint16_t wqe_free; /* available wqe remain. */
 	uint16_t mbuf_off; /* data offset in current mbuf. */