From: Zaiyu Wang <zaiyuwang@trustnetic.com>
To: dev@dpdk.org
Cc: Zaiyu Wang <zaiyuwang@trustnetic.com>,
Jiawen Wu <jiawenwu@trustnetic.com>,
Jian Wang <jianwang@trustnetic.com>
Subject: [PATCH v3 09/15] net/txgbe: add TX head Write-Back mode for Amber-Lite NICs
Date: Thu, 26 Jun 2025 16:02:14 +0800 [thread overview]
Message-ID: <20250626080221.22488-10-zaiyuwang@trustnetic.com> (raw)
In-Reply-To: <20250626080221.22488-1-zaiyuwang@trustnetic.com>
Add TX head Write-Back mode for Amber-Lite NICs. When enabled, the
hardware no longer individually rewrites descriptors but intermittently
notifies the driver of processed descriptor indices. This feature
significantly improves performance and is enabled by default in the
driver. Users can configure it via tx_headwb and tx_headwb_size in devargs.
Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com>
---
drivers/net/txgbe/base/txgbe_regs.h | 7 ++
drivers/net/txgbe/base/txgbe_type.h | 6 ++
drivers/net/txgbe/txgbe_ethdev.c | 9 ++
drivers/net/txgbe/txgbe_rxtx.c | 126 ++++++++++++++++++----
drivers/net/txgbe/txgbe_rxtx.h | 3 +
drivers/net/txgbe/txgbe_rxtx_vec_common.h | 27 +++--
6 files changed, 151 insertions(+), 27 deletions(-)
diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h
index 7ee7712e53..17257442f3 100644
--- a/drivers/net/txgbe/base/txgbe_regs.h
+++ b/drivers/net/txgbe/base/txgbe_regs.h
@@ -1402,6 +1402,13 @@ enum txgbe_5tuple_protocol {
#define TXGBE_TXCFG_WTHRESH_MASK_AML MS(16, 0x1FF)
#define TXGBE_TXCFG_WTHRESH(v) LS(v, 16, 0x7F)
#define TXGBE_TXCFG_FLUSH MS(26, 0x1)
+#define TXGBE_PX_TR_CFG_HEAD_WB MS(27, 0x1) /* amlite head wb */
+#define TXGBE_PX_TR_CFG_HEAD_WB_64BYTE MS(28, 0x1) /* amlite head wb 64byte */
+#define TXGBE_PX_TR_CFG_HEAD_WB_MASK MS(27, 0x3)
+
+/* amlite: tx head wb */
+#define TXGBE_PX_TR_HEAD_ADDRL(_i) (0x03028 + ((_i) * 0x40))
+#define TXGBE_PX_TR_HEAD_ADDRH(_i) (0x0302C + ((_i) * 0x40))
#define TXGBE_TDM_DESC_CHK(i) (0x0180B0 + (i) * 4) /*0-3*/
#define TXGBE_TDM_DESC_NONFATAL(i) (0x0180C0 + (i) * 4) /*0-3*/
diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h
index 8005283a26..5692883f60 100644
--- a/drivers/net/txgbe/base/txgbe_type.h
+++ b/drivers/net/txgbe/base/txgbe_type.h
@@ -723,6 +723,8 @@ struct txgbe_phy_info {
#define TXGBE_DEVARG_FFE_MAIN "ffe_main"
#define TXGBE_DEVARG_FFE_PRE "ffe_pre"
#define TXGBE_DEVARG_FFE_POST "ffe_post"
+#define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb"
+#define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size"
static const char * const txgbe_valid_arguments[] = {
TXGBE_DEVARG_BP_AUTO,
@@ -733,6 +735,8 @@ static const char * const txgbe_valid_arguments[] = {
TXGBE_DEVARG_FFE_MAIN,
TXGBE_DEVARG_FFE_PRE,
TXGBE_DEVARG_FFE_POST,
+ TXGBE_DEVARG_TX_HEAD_WB,
+ TXGBE_DEVARG_TX_HEAD_WB_SIZE,
NULL
};
@@ -783,6 +787,8 @@ struct txgbe_devargs {
u16 poll;
u16 present;
u16 sgmii;
+ u16 tx_headwb;
+ u16 tx_headwb_size;
};
struct txgbe_hw {
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index a854b40b9f..ed84594105 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -513,6 +513,9 @@ txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
u16 ffe_main = 27;
u16 ffe_pre = 8;
u16 ffe_post = 44;
+ /* New devargs for amberlite config */
+ u16 tx_headwb = 1;
+ u16 tx_headwb_size = 16;
if (devargs == NULL)
goto null;
@@ -537,6 +540,10 @@ txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
&txgbe_handle_devarg, &ffe_pre);
rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST,
&txgbe_handle_devarg, &ffe_post);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_TX_HEAD_WB,
+ &txgbe_handle_devarg, &tx_headwb);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_TX_HEAD_WB_SIZE,
+ &txgbe_handle_devarg, &tx_headwb_size);
rte_kvargs_free(kvlist);
null:
@@ -544,6 +551,8 @@ txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
hw->devarg.poll = poll;
hw->devarg.present = present;
hw->devarg.sgmii = sgmii;
+ hw->devarg.tx_headwb = tx_headwb;
+ hw->devarg.tx_headwb_size = tx_headwb_size;
hw->phy.ffe_set = ffe_set;
hw->phy.ffe_main = ffe_main;
hw->phy.ffe_pre = ffe_pre;
diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c
index 558ffbf73f..28c384af73 100644
--- a/drivers/net/txgbe/txgbe_rxtx.c
+++ b/drivers/net/txgbe/txgbe_rxtx.c
@@ -92,14 +92,29 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq)
int i, nb_free = 0;
struct rte_mbuf *m, *free[RTE_TXGBE_TX_MAX_FREE_BUF_SZ];
- /* check DD bit on threshold descriptor */
- status = txq->tx_ring[txq->tx_next_dd].dw3;
- if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) {
- if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
- txgbe_set32_masked(txq->tdc_reg_addr,
- TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
- return 0;
- }
+ if (txq->headwb_mem) {
+ uint16_t tx_last_dd = txq->nb_tx_desc +
+ txq->tx_next_dd - txq->tx_free_thresh;
+ if (tx_last_dd >= txq->nb_tx_desc)
+ tx_last_dd -= txq->nb_tx_desc;
+
+ volatile uint16_t head = (uint16_t)*txq->headwb_mem;
+
+ if (txq->tx_next_dd > head && head > tx_last_dd)
+ return 0;
+ else if (tx_last_dd > txq->tx_next_dd &&
+ (head > tx_last_dd || head < txq->tx_next_dd))
+ return 0;
+ } else {
+ /* check DD bit on threshold descriptor */
+ status = txq->tx_ring[txq->tx_next_dd].dw3;
+ if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) {
+ if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
+ txgbe_set32_masked(txq->tdc_reg_addr,
+ TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
+ return 0;
+ }
+}
/*
* first buffer to free from S/W ring is at index
@@ -628,17 +643,28 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq)
/* Check to make sure the last descriptor to clean is done */
desc_to_clean_to = sw_ring[desc_to_clean_to].last_id;
status = txr[desc_to_clean_to].dw3;
- if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) {
- PMD_TX_FREE_LOG(DEBUG,
- "TX descriptor %4u is not done"
- "(port=%d queue=%d)",
- desc_to_clean_to,
- txq->port_id, txq->queue_id);
- if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
- txgbe_set32_masked(txq->tdc_reg_addr,
- TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
- /* Failed to clean any descriptors, better luck next time */
- return -(1);
+
+ if (txq->headwb_mem) {
+ u32 head = *txq->headwb_mem;
+
+ PMD_TX_FREE_LOG(DEBUG, "queue[%02d]: headwb_mem = %03d, desc_to_clean_to = %03d",
+ txq->reg_idx, head, desc_to_clean_to);
+ /* we have caught up to head, no work left to do */
+ if (desc_to_clean_to == head)
+ return -(1);
+ } else {
+ if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) {
+ PMD_TX_FREE_LOG(DEBUG,
+ "TX descriptor %4u is not done"
+ "(port=%d queue=%d)",
+ desc_to_clean_to,
+ txq->port_id, txq->queue_id);
+ if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
+ txgbe_set32_masked(txq->tdc_reg_addr,
+ TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
+ /* Failed to clean any descriptors, better luck next time */
+ return -(1);
+ }
}
/* Figure out how many descriptors will be cleaned */
@@ -2244,6 +2270,8 @@ txgbe_tx_queue_release(struct txgbe_tx_queue *txq)
txq->ops->release_mbufs(txq);
txq->ops->free_swring(txq);
rte_memzone_free(txq->mz);
+ if (txq->headwb_mem)
+ rte_memzone_free(txq->headwb);
rte_free(txq);
}
}
@@ -2380,6 +2408,43 @@ txgbe_get_tx_port_offloads(struct rte_eth_dev *dev)
return tx_offload_capa;
}
+static int
+txgbe_setup_headwb_resources(struct rte_eth_dev *dev,
+ void *tx_queue,
+ unsigned int socket_id)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ const struct rte_memzone *headwb;
+ struct txgbe_tx_queue *txq = tx_queue;
+ u8 i, headwb_size = 0;
+
+ if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) {
+ txq->headwb_mem = NULL;
+ return 0;
+ }
+
+ headwb_size = hw->devarg.tx_headwb_size;
+ headwb = rte_eth_dma_zone_reserve(dev, "tx_headwb_mem", txq->queue_id,
+ sizeof(u32) * headwb_size,
+ TXGBE_ALIGN, socket_id);
+
+ if (headwb == NULL) {
+ DEBUGOUT("Fail to setup headwb resources: no mem");
+ txgbe_tx_queue_release(txq);
+ return -ENOMEM;
+ }
+
+ txq->headwb = headwb;
+ txq->headwb_dma = TMZ_PADDR(headwb);
+ txq->headwb_mem = (uint32_t *)TMZ_VADDR(headwb);
+
+ /* Zero out headwb_mem memory */
+ for (i = 0; i < headwb_size; i++)
+ txq->headwb_mem[i] = 0;
+
+ return 0;
+}
+
int __rte_cold
txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
@@ -2392,6 +2457,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
struct txgbe_hw *hw;
uint16_t tx_free_thresh;
uint64_t offloads;
+ s32 err = 0;
PMD_INIT_FUNC_TRACE();
hw = TXGBE_DEV_HW(dev);
@@ -2511,12 +2577,15 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
/* set up scalar TX function as appropriate */
txgbe_set_tx_function(dev, txq);
+ if (hw->devarg.tx_headwb)
+ err = txgbe_setup_headwb_resources(dev, txq, socket_id);
+
txq->ops->reset(txq);
txq->desc_error = 0;
dev->data->tx_queues[queue_idx] = txq;
- return 0;
+ return err;
}
/**
@@ -4658,6 +4727,23 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev)
/* Setup the HW Tx Head and TX Tail descriptor pointers */
wr32(hw, TXGBE_TXRP(txq->reg_idx), 0);
wr32(hw, TXGBE_TXWP(txq->reg_idx), 0);
+
+ if ((hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) &&
+ hw->devarg.tx_headwb) {
+ uint32_t txdctl;
+
+ wr32(hw, TXGBE_PX_TR_HEAD_ADDRL(txq->reg_idx),
+ (uint32_t)(txq->headwb_dma & BIT_MASK32));
+ wr32(hw, TXGBE_PX_TR_HEAD_ADDRH(txq->reg_idx),
+ (uint32_t)(txq->headwb_dma >> 32));
+ if (hw->devarg.tx_headwb_size == 16)
+ txdctl = TXGBE_PX_TR_CFG_HEAD_WB |
+ TXGBE_PX_TR_CFG_HEAD_WB_64BYTE;
+ else
+ txdctl = TXGBE_PX_TR_CFG_HEAD_WB;
+ wr32m(hw, TXGBE_TXCFG(txq->reg_idx),
+ TXGBE_PX_TR_CFG_HEAD_WB_MASK, txdctl);
+ }
}
#ifndef RTE_LIB_SECURITY
diff --git a/drivers/net/txgbe/txgbe_rxtx.h b/drivers/net/txgbe/txgbe_rxtx.h
index 622a0d3981..b1ac03576f 100644
--- a/drivers/net/txgbe/txgbe_rxtx.h
+++ b/drivers/net/txgbe/txgbe_rxtx.h
@@ -414,6 +414,9 @@ struct txgbe_tx_queue {
const struct rte_memzone *mz;
uint64_t desc_error;
bool resetting;
+ const struct rte_memzone *headwb;
+ uint64_t headwb_dma;
+ volatile uint32_t *headwb_mem;
};
struct txgbe_txq_ops {
diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h
index cf67df66d8..00847d087b 100644
--- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h
+++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h
@@ -89,13 +89,26 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq)
int nb_free = 0;
struct rte_mbuf *m, *free[RTE_TXGBE_TX_MAX_FREE_BUF_SZ];
- /* check DD bit on threshold descriptor */
- status = txq->tx_ring[txq->tx_next_dd].dw3;
- if (!(status & TXGBE_TXD_DD)) {
- if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
- txgbe_set32_masked(txq->tdc_reg_addr,
- TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
- return 0;
+ if (txq->headwb_mem) {
+ uint16_t tx_last_dd = txq->nb_tx_desc +
+ txq->tx_next_dd - txq->tx_free_thresh;
+ if (tx_last_dd >= txq->nb_tx_desc)
+ tx_last_dd -= txq->nb_tx_desc;
+ volatile uint16_t head = (uint16_t)*txq->headwb_mem;
+ if (txq->tx_next_dd > head && head > tx_last_dd)
+ return 0;
+ else if (tx_last_dd > txq->tx_next_dd &&
+ (head > tx_last_dd || head < txq->tx_next_dd))
+ return 0;
+ } else {
+ /* check DD bit on threshold descriptor */
+ status = txq->tx_ring[txq->tx_next_dd].dw3;
+ if (!(status & TXGBE_TXD_DD)) {
+ if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
+ txgbe_set32_masked(txq->tdc_reg_addr,
+ TXGBE_TXCFG_FLUSH, TXGBE_TXCFG_FLUSH);
+ return 0;
+ }
}
n = txq->tx_free_thresh;
--
2.21.0.windows.1
next prev parent reply other threads:[~2025-06-26 8:10 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-18 9:41 [PATCH 0/2] *** Wangxun new NIC support *** Zaiyu Wang
2025-04-18 9:41 ` [PATCH 1/2] net/txgbe: add support for Wangxun new NIC Amber-Lite 25g/40g Zaiyu Wang
2025-04-18 9:41 ` [PATCH 2/2] net/txgbe: add basic code for Amber-Liter NIC configuration Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 00/15] Wangxun new NIC support Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 01/15] net/txgbe: add basic information for Amber-Lite 25G/40G NICs Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 02/15] net/txgbe: add new SW-FW mailbox interface Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 03/15] net/txgbe: add identification support for new SFP/QSFP modules Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 04/15] net/txgbe: add basic link configuration for Amber-Lite NICs Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 05/15] net/txgbe: add support for PHY configuration via SW-FW mailbox Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 06/15] net/txgbe: add RX&TX support for Amber-Lite NICs Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 07/15] net/txgbe: add hardware reset change " Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 08/15] net/txgbe: add MAC reconfiguration to avoid packet loss Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 09/15] net/txgbe: add TX head Write-Back mode for Amber-Lite NICs Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 10/15] net/txgbe: add RX desc merge " Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 11/15] net/txgbe: add FEC support for Amber-Lite 25G NICs Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 12/15] net/txgbe: add GPIO configuration Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 13/15] net/txgbe: disable unstable features Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 14/15] net/txgbe: add other hardware-related changes Zaiyu Wang
2025-06-25 12:50 ` [PATCH v2 15/15] doc: update for txgbe Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 00/15] Wangxun new NIC support Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 01/15] net/txgbe: add basic information for Amber-Lite 25G/40G NICs Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 02/15] net/txgbe: add new SW-FW mailbox interface Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 03/15] net/txgbe: add identification support for new SFP/QSFP modules Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 04/15] net/txgbe: add basic link configuration for Amber-Lite NICs Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 05/15] net/txgbe: add support for PHY configuration via SW-FW mailbox Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 06/15] net/txgbe: add RX&TX support for Amber-Lite NICs Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 07/15] net/txgbe: add hardware reset change " Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 08/15] net/txgbe: add MAC reconfiguration to avoid packet loss Zaiyu Wang
2025-06-26 8:02 ` Zaiyu Wang [this message]
2025-06-26 8:02 ` [PATCH v3 10/15] net/txgbe: add RX desc merge mode for Amber-Lite NICs Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 11/15] net/txgbe: add FEC support for Amber-Lite 25G NICs Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 12/15] net/txgbe: add GPIO configuration Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 13/15] net/txgbe: disable unstable features Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 14/15] net/txgbe: add other hardware-related changes Zaiyu Wang
2025-06-26 8:02 ` [PATCH v3 15/15] doc: update for txgbe Zaiyu Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250626080221.22488-10-zaiyuwang@trustnetic.com \
--to=zaiyuwang@trustnetic.com \
--cc=dev@dpdk.org \
--cc=jianwang@trustnetic.com \
--cc=jiawenwu@trustnetic.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).