From: Jie Liu <[email protected]> This patch implements the 'tx_done_cleanup' ethdev ops in the sxe2 PMD. This interface allows applications to explicitly request the driver to release mbufs that have been transmitted and are no longer needed by the hardware.
The implementation iterates through the Tx ring, checking the status of the descriptors starting from the last cleaned tail. It releases the corresponding mbufs back to the mempool until either the requested number of packets are freed or no more completed descriptors are found. Signed-off-by: Jie Liu <[email protected]> --- drivers/net/sxe2/sxe2_ethdev.c | 1 + drivers/net/sxe2/sxe2_txrx.h | 1 + drivers/net/sxe2/sxe2_txrx_poll.c | 102 ++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c index d1bdc22bd0..8d66e5d8c5 100644 --- a/drivers/net/sxe2/sxe2_ethdev.c +++ b/drivers/net/sxe2/sxe2_ethdev.c @@ -290,6 +290,7 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = { .txq_info_get = sxe2_tx_queue_info_get, .rx_burst_mode_get = sxe2_rx_burst_mode_get, .tx_burst_mode_get = sxe2_tx_burst_mode_get, + .tx_done_cleanup = sxe2_tx_done_cleanup, }; struct sxe2_pci_map_bar_info *sxe2_dev_get_bar_info(struct sxe2_adapter *adapter, diff --git a/drivers/net/sxe2/sxe2_txrx.h b/drivers/net/sxe2/sxe2_txrx.h index 61c6641e49..6d3d7455c2 100644 --- a/drivers/net/sxe2/sxe2_txrx.h +++ b/drivers/net/sxe2/sxe2_txrx.h @@ -12,6 +12,7 @@ int32_t __rte_cold sxe2_tx_simple_batch_support_check(struct rte_eth_dev *dev, uint32_t *batch_flags); uint16_t sxe2_tx_pkts_prepare(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); +int32_t sxe2_tx_done_cleanup(void *txq, uint32_t free_cnt); void sxe2_tx_mode_func_set(struct rte_eth_dev *dev); void __rte_cold sxe2_rx_queue_reset(struct sxe2_rx_queue *rxq); void sxe2_rx_mode_func_set(struct rte_eth_dev *dev); diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c index 7ec70d952e..b9d34afb31 100644 --- a/drivers/net/sxe2/sxe2_txrx_poll.c +++ b/drivers/net/sxe2/sxe2_txrx_poll.c @@ -10,8 +10,10 @@ #include <ethdev_driver.h> #include "sxe2_osal.h" #include "sxe2_txrx_common.h" +#include "sxe2_txrx_vec_common.h" #include "sxe2_txrx_poll.h" #include "sxe2_txrx.h" +#include "sxe2_txrx_vec.h" #include "sxe2_queue.h" #include "sxe2_ethdev.h" #include "sxe2_common_log.h" @@ -116,6 +118,106 @@ static inline int32_t sxe2_tx_cleanup(struct sxe2_tx_queue *txq) return ret; } +static int32_t sxe2_tx_done_cleanup_simple(struct sxe2_tx_queue *txq, uint32_t free_cnt) +{ + uint32_t free_cnt_align; + uint32_t free_cnt_once; + uint32_t i; + + if (free_cnt == 0 || free_cnt > txq->ring_depth) + free_cnt = txq->ring_depth; + + free_cnt_align = free_cnt - (free_cnt % txq->rs_thresh); + for (i = 0; i < free_cnt_align; i += free_cnt_once) { + if ((txq->ring_depth - txq->desc_free_num) < txq->rs_thresh) + break; + + free_cnt_once = sxe2_tx_bufs_free(txq); + if (free_cnt_once == 0) + break; + } + + return i; +} + +static int32_t sxe2_tx_done_cleanup_normal(struct sxe2_tx_queue *txq, uint32_t free_cnt) +{ + struct sxe2_tx_buffer *buffer_ring = txq->buffer_ring; + int32_t ret; + uint16_t clean_last_idx, clean_idx; + uint16_t clean_last, clean_once; + uint16_t pkt_cnt, i; + + if (txq->desc_free_num == 0 && sxe2_tx_cleanup(txq) != 0) { + ret = 0; + goto l_end; + } + + if (free_cnt == 0) + free_cnt = txq->ring_depth; + + clean_last_idx = txq->next_use; + clean_idx = buffer_ring[clean_last_idx].next_id; + clean_once = txq->desc_free_num; + clean_last = txq->desc_free_num; + + for (pkt_cnt = 0; pkt_cnt < free_cnt;) { + for (i = 0; ((i < clean_once) && + (pkt_cnt < free_cnt) && + clean_idx != clean_last_idx); ++i) { + if (buffer_ring[clean_idx].mbuf != NULL) { + rte_pktmbuf_free_seg(buffer_ring[clean_idx].mbuf); + buffer_ring[clean_idx].mbuf = NULL; + if (buffer_ring[clean_idx].last_id == clean_idx) + pkt_cnt++; + } + clean_idx = buffer_ring[clean_idx].next_id; + } + + if ((txq->rs_thresh > (txq->ring_depth - txq->desc_free_num)) || + clean_idx == clean_last_idx) + break; + + if (pkt_cnt < free_cnt) { + if (sxe2_tx_cleanup(txq) != 0) + break; + + clean_once = txq->desc_free_num - clean_last; + clean_last = txq->desc_free_num; + } + } + + ret = pkt_cnt; +l_end: + return ret; +} + +int32_t sxe2_tx_done_cleanup(void *tx_queue, uint32_t free_cnt) +{ + struct sxe2_tx_queue *txq = (struct sxe2_tx_queue *)tx_queue; + struct sxe2_adapter *adapter; + int32_t ret; + + if (txq == NULL) { + ret = 0; + goto l_end; + } + + adapter = txq->vsi->adapter; + if (adapter->q_ctxt.tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) + ret = -ENOTSUP; + else if (adapter->q_ctxt.tx_mode_flags & SXE2_TX_MODE_SIMPLE_BATCH) + ret = sxe2_tx_done_cleanup_simple(txq, free_cnt); + else + ret = sxe2_tx_done_cleanup_normal(txq, free_cnt); + + PMD_LOG_DEBUG(TX, "TX cleanup done desc queue_id=%u free_cnt=%d.", + txq->queue_id, ret); + +l_end: + return ret; +} + static __rte_always_inline uint32_t sxe2_tx_pkt_data_desc_count(struct rte_mbuf *tx_pkt) { -- 2.47.3

