From: Jun Yang <[email protected]> Split a dedicated Tx fast path out of dpaa2_dev_tx() for the common no-confirmation configuration, keeping the hot enqueue loop free of the Tx-conf and timestamp bookkeeping needed only by the slow path.
- Add dpaa2_dev_tx_fast() for the DPAA2_TX_NO_CONF case. dpaa2_dev_tx() builds the enqueue descriptor and dispatches straight to it, so the common path no longer runs the per-burst Tx-conf drain or the per-packet timestamp accounting. - Factor the retry enqueue loop into dpaa2_dev_tx_enqueue_multiple() and the ordered-queue tail into dpaa2_dev_tx_multi_ordered(), shared by both the fast and slow paths to remove duplicated code. - Zero-initialise fd_arr in the slow path and mark the rarely taken branches (congestion retry, VLAN insert, ordered, timestamp) unlikely. This reduces per-packet work on the common Tx path. Signed-off-by: Jun Yang <[email protected]> --- drivers/net/dpaa2/dpaa2_rxtx.c | 158 +++++++++++++++++++++++++-------- 1 file changed, 122 insertions(+), 36 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 2af5a4745d..312c9bd7d5 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1511,6 +1511,114 @@ dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } +static __rte_always_inline uint16_t __rte_hot +dpaa2_dev_tx_enqueue_multiple(struct qbman_swp *swp, + const struct qbman_fd *fd, uint16_t to_send, + const struct qbman_eq_desc *eqdesc) +{ + uint16_t loop = 0, retry_count = 0; + int eq_ret; + + while (loop < to_send) { + eq_ret = qbman_swp_enqueue_multiple(swp, eqdesc, + &fd[loop], NULL, to_send - loop); + if (unlikely(eq_ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + loop += eq_ret; + retry_count = 0; + } + } + + return loop; +} + +static __rte_noinline uint16_t +dpaa2_dev_tx_multi_ordered(struct dpaa2_queue *dpaa2_q, + struct rte_mbuf **bufs, uint16_t nb_pkts) +{ + uint16_t to_send, order_tx = 0, total = 0; + +order_tx_again: + to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; + order_tx = dpaa2_dev_tx_ordered(dpaa2_q, bufs, to_send); + bufs += order_tx; + nb_pkts -= order_tx; + total += order_tx; + if (nb_pkts && order_tx >= to_send) + goto order_tx_again; + + return total; +} + +static __rte_always_inline uint16_t __rte_hot +dpaa2_dev_tx_fast(struct dpaa2_queue *dpaa2_q, struct rte_mbuf **bufs, + uint16_t nb_pkts, struct qbman_swp *swp, struct qbman_fd *fd_arr, + const struct qbman_eq_desc *eqdesc, struct rte_mempool *hw_mp) +{ + /* Function to transmit the frames to given device and VQ*/ + uint32_t loop, retry_count, frames_to_send; + int32_t ret, order = false; + uint16_t num_tx = 0, eq_ret = 0; + +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } + + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; + + for (loop = 0; loop < frames_to_send; loop++) { + if (unlikely(dpaa2_mbuf_seq_is_flag_set((*bufs), + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA)))) { + order = true; + break; + } + + if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) + break; + } + if (likely(RTE_MBUF_DIRECT(*bufs) && + (*bufs)->pool->ops_index == hw_mp->ops_index && + (*bufs)->nb_segs == 1 && rte_mbuf_refcnt_read(*bufs) == 1)) { + DPAA2_MBUF_TO_CONTIG_FD((*bufs), &fd_arr[loop], + mempool_to_bpid((*bufs)->pool)); + ret = 0; + } else if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, DPAA2_TX_NO_CONF, false); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, DPAA2_TX_NO_CONF, false); + } + if (ret) + break; + bufs++; + } + + eq_ret = dpaa2_dev_tx_enqueue_multiple(swp, fd_arr, loop, eqdesc); + num_tx += eq_ret; + nb_pkts -= eq_ret; + if (unlikely(nb_pkts > 0 && !ret && !order)) + goto tx_again; + +skip_tx: + dpaa2_q->tx_pkts += num_tx; + if (unlikely(order && eq_ret >= loop)) + num_tx += dpaa2_dev_tx_multi_ordered(dpaa2_q, bufs, nb_pkts); + + return num_tx; +} + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1519,12 +1627,12 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ uint32_t loop, retry_count, i, ptp_n, frames_to_send; - int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set, order = false, eq_ret = 0; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set, order = false; + struct qbman_fd fd_arr[MAX_TX_RING_SLOTS] = {0}; struct qbman_eq_desc eqdesc; struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; - uint16_t num_tx = 0, order_tx; + uint16_t num_tx = 0, eq_ret = 0; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; struct rte_mempool *hw_mp; @@ -1549,15 +1657,15 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } hw_mp = priv->bp_list->mp; - if (dpaa2_q->tx_conf_queue) - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue, false); - /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); + if (likely(priv->tx_conf_type == DPAA2_TX_NO_CONF)) + return dpaa2_dev_tx_fast(dpaa2_q, bufs, nb_pkts, swp, fd_arr, &eqdesc, hw_mp); - /*Clear the unused FD fields before sending*/ + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue, false); tx_again: /*Check if the queue is congested*/ @@ -1617,27 +1725,13 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) bufs++; } - frames_to_send = loop; - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - eq_ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], NULL, frames_to_send - loop); - if (unlikely(eq_ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - loop += eq_ret; - retry_count = 0; - } - } + eq_ret = dpaa2_dev_tx_enqueue_multiple(swp, fd_arr, loop, &eqdesc); + num_tx += eq_ret; + nb_pkts -= eq_ret; - num_tx += loop; - nb_pkts -= loop; if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { - for (i = 0; i < loop; i++) { - if (tstamp[i]) { + for (i = 0; i < eq_ret; i++) { + if (unlikely(tstamp[i])) { rte_atomic_fetch_add_explicit(&dpaa2_q->tx_conf_queue->ts_to_cnfd, 1, rte_memory_order_relaxed); } @@ -1648,16 +1742,8 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) skip_tx: dpaa2_q->tx_pkts += num_tx; - if (order && eq_ret >= 0) { -order_tx_again: - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; - nb_pkts -= frames_to_send; - order_tx = dpaa2_dev_tx_ordered(queue, bufs, frames_to_send); - num_tx += order_tx; - bufs += frames_to_send; - if (nb_pkts && order_tx >= frames_to_send) - goto order_tx_again; - } + if (unlikely(order && eq_ret >= loop)) + num_tx += dpaa2_dev_tx_multi_ordered(dpaa2_q, bufs, nb_pkts); return num_tx; } -- 2.43.0

