summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViacheslav Ovsiienko <viacheslavo@mellanox.com>2019-08-05 13:03:54 +0000
committerRaslan Darawsheh <rasland@mellanox.com>2019-08-06 17:42:12 +0200
commitf32a3f5216a33839799932451dde305759082efb (patch)
treef64006837b51e767fb59f2b2c409ccd6f46943f1
parent3502b059251517785bd3232a97f56fb239606183 (diff)
downloaddpdk-f32a3f5216a33839799932451dde305759082efb.zip
dpdk-f32a3f5216a33839799932451dde305759082efb.tar.gz
dpdk-f32a3f5216a33839799932451dde305759082efb.tar.xz
net/mlx5: fix completion queue overflow for large burst
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>
-rw-r--r--drivers/net/mlx5/mlx5_rxtx.c36
-rw-r--r--drivers/net/mlx5/mlx5_rxtx.h1
2 files changed, 24 insertions, 13 deletions
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 0c9c217..3e51bb0 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -2142,8 +2142,7 @@ mlx5_tx_request_completion(struct mlx5_txq_data *restrict txq,
uint16_t head = txq->elts_head;
unsigned int part;
- part = MLX5_TXOFF_CONFIG(INLINE) ? 0 : loc->pkts_sent -
- (MLX5_TXOFF_CONFIG(MULTI) ? loc->pkts_copy : 0);
+ part = MLX5_TXOFF_CONFIG(INLINE) ? 0 : loc->pkts_sent - loc->pkts_copy;
head += part;
if ((uint16_t)(head - txq->elts_comp) >= MLX5_TX_COMP_THRESH ||
(MLX5_TXOFF_CONFIG(INLINE) &&
@@ -4520,6 +4519,14 @@ mlx5_tx_burst_tmpl(struct mlx5_txq_data *restrict txq,
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
@@ -4527,9 +4534,7 @@ mlx5_tx_burst_tmpl(struct mlx5_txq_data *restrict txq,
* - 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.
@@ -4546,10 +4551,7 @@ mlx5_tx_burst_tmpl(struct mlx5_txq_data *restrict txq,
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
@@ -4715,8 +4717,8 @@ enter_send_single:
*/
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
@@ -4725,8 +4727,7 @@ enter_send_single:
*/
mlx5_tx_dbrec_cond_wmb(txq, loc.wqe_last, 0);
/* Not all of the mbufs may be stored into elts yet. */
- part = MLX5_TXOFF_CONFIG(INLINE) ? 0 : loc.pkts_sent -
- (MLX5_TXOFF_CONFIG(MULTI) ? loc.pkts_copy : 0);
+ part = MLX5_TXOFF_CONFIG(INLINE) ? 0 : loc.pkts_sent - loc.pkts_copy;
if (!MLX5_TXOFF_CONFIG(INLINE) && part) {
/*
* There are some single-segment mbufs not stored in elts.
@@ -4738,6 +4739,7 @@ enter_send_single:
* inlined mbufs.
*/
mlx5_tx_copy_elts(txq, pkts + loc.pkts_copy, part, olx);
+ loc.pkts_copy = loc.pkts_sent;
}
#ifdef MLX5_PMD_SOFT_COUNTERS
/* Increment sent packets counter. */
@@ -4745,6 +4747,14 @@ enter_send_single:
#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. */