* [PATCH 01/13] net/txgbe: fix e56 PHY configuration error [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 02/13] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (23 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 02/13] net/txgbe: fix incorrect link state in 10G forced mode [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> 2026-08-27 11:41 ` [PATCH 01/13] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 03/13] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (22 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..05eac68f3b 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -197,6 +197,8 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, ret_status = txgbe_set_link_to_amlite(hw, speed); if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; + else + hw->link_valid = true; rte_spinlock_unlock(&hw->phy_lock); for (i = 0; i < 4; i++) { -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 03/13] net/txgbe: do not force reconfig on link retry [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> 2026-08-27 11:41 ` [PATCH 01/13] net/txgbe: fix e56 PHY configuration error Zaiyu Wang 2026-08-27 11:41 ` [PATCH 02/13] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 04/13] net/txgbe: set i2c sda hold time Zaiyu Wang ` (21 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4d2746371b..b0d2bc3450 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3286,7 +3286,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 04/13] net/txgbe: set i2c sda hold time [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-08-27 11:41 ` [PATCH 03/13] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 05/13] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (20 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 05/13] net/txgbe: fix link speed display info for 10G mode [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-08-27 11:41 ` [PATCH 04/13] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 06/13] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (19 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, and include 10G in the default advertised speed mask in txgbe_dev_start() so a 10G link is reported with the correct speed. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 05eac68f3b..90d4453b06 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index b0d2bc3450..ae755996e6 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1912,7 +1912,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 06/13] net/txgbe: remove stale outer UDP checksum offload flag [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-08-27 11:41 ` [PATCH 05/13] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:41 ` [PATCH 07/13] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang ` (18 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 07/13] net/txgbe: add offload support for tunnel type UDP [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-08-27 11:41 ` [PATCH 06/13] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-08-27 11:41 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 08/13] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (17 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The non-standard RTE_MBUF_F_TX_TUNNEL_UDP tunnel type (UDP encapsulation carrying either VXLAN or GENEVE) is not handled: txgbe_set_xmit_ctx() falls into the "unknown tunnel type" case and txgbe_get_tun_len() cannot compute the tunnel length, so tunneled packets are sent with a wrong descriptor or dropped. Handle RTE_MBUF_F_TX_TUNNEL_UDP by parsing the UDP destination port (6081 -> GENEVE, otherwise VXLAN) to select the inner tunnel type, so the correct tunnel length and packet type are reported. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index a295666f9d..cd958b4aab 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -419,6 +419,7 @@ txgbe_set_xmit_ctx(struct txgbe_tx_queue *txq, break; case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: case RTE_MBUF_F_TX_TUNNEL_GENEVE: tunnel_seed |= TXGBE_TXD_ETYPE_UDP; break; @@ -593,6 +594,7 @@ tx_desc_ol_flags_to_ptype(uint64_t oflags) switch (oflags & RTE_MBUF_F_TX_TUNNEL_MASK) { case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: ptype |= RTE_PTYPE_TUNNEL_GRENAT; break; case RTE_MBUF_F_TX_TUNNEL_GRE: @@ -713,8 +715,21 @@ txgbe_get_tun_len(struct rte_mbuf *mbuf) const struct txgbe_genevehdr *gh; const struct txgbe_grehdr *grh; struct txgbe_grehdr grehdr; + struct txgbe_udphdr udphdr; + const struct txgbe_udphdr *uh; uint8_t tun_len; + /* Check for UDP tunneling */ + if ((mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) == RTE_MBUF_F_TX_TUNNEL_UDP) { + mbuf->ol_flags &= ~RTE_MBUF_F_TX_TUNNEL_UDP; + uh = rte_pktmbuf_read(mbuf, mbuf->outer_l2_len + mbuf->outer_l3_len, + sizeof(udphdr), &udphdr); + if (uh->dest == rte_cpu_to_be_16(6081)) + mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GENEVE; + else + mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_VXLAN; + } + switch (mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) { case RTE_MBUF_F_TX_TUNNEL_IPIP: tun_len = 0; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 08/13] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-08-27 11:41 ` [PATCH 07/13] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 09/13] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (16 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index ae755996e6..9a29539f14 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2987,6 +2987,20 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3110,10 +3124,22 @@ txgbe_dev_detect_sfp(void *param) PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 09/13] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 08/13] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 10/13] net/txgbe: add backplane FFE and capability devargs Zaiyu Wang ` (15 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the port is started, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 90d4453b06..bfb8a4bc7f 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -176,6 +176,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 9a29539f14..38c58323e7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2015,6 +2015,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3096,7 +3101,7 @@ txgbe_dev_detect_sfp(void *param) struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); @@ -3104,6 +3109,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3142,6 +3152,11 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + dev->data->dev_started) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 10/13] net/txgbe: add backplane FFE and capability devargs [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 09/13] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 11/13] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (14 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Two backplane configuration knobs are missing. The 25G E56 PHY has a second pre-cursor tap that cannot be tuned: with ffe_set enabled, the pre2 value is never applied. On the 40G PHY, a user supplied FFE value only reaches the first lane, because the register holds one FFE byte per lane and the value is not replicated over the four lanes. The advertised 40G backplane capability is hardwired to KR4+CR4; there is no way to advertise only 40GBASE-KR4 or only 40GBASE-CR4. Add the ffe_pre2 and bp_capa devargs, use the E56 PHY FFE defaults for AML/AML40 when ffe_set is enabled, and replicate the user FFE value over the four 40G lanes. The devargs are parsed after the shared code init so the MAC type is known when picking the defaults. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 11 ++++++++ drivers/net/txgbe/base/txgbe_e56.h | 5 ++++ drivers/net/txgbe/base/txgbe_type.h | 12 ++++++--- drivers/net/txgbe/txgbe_ethdev.c | 39 +++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..d56fb3b99a 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -142,6 +142,11 @@ Please note that following ``devargs`` are only set for backplane NICs. PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + - ``ffe_post`` (default **44**) PHY parameter used for user debugging. Setting other values to @@ -177,6 +182,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 38c58323e7..181a1df523 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -531,6 +531,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u8 pballoc = 0; @@ -539,6 +540,22 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; + + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. + */ + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } if (devargs == NULL) goto null; @@ -561,6 +578,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -573,6 +592,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -586,7 +607,17 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; + + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; @@ -690,7 +721,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -698,6 +728,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); @@ -6478,12 +6511,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 11/13] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 10/13] net/txgbe: add backplane FFE and capability devargs Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 12/13] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang ` (13 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 +++++++ drivers/net/txgbe/base/txgbe_hw.c | 22 ++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 ++++++- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index d56fb3b99a..a580450726 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -188,6 +188,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..2b44c30883 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,24 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, 0x1400, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else { + txgbe_acquire_swfw_sync(hw, 1); + hw->phy.write_i2c_eeprom(hw, 86, 0xf); + txgbe_release_swfw_sync(hw, 1); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3307,9 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + txgbe_acquire_swfw_sync(hw, 1); + hw->phy.write_i2c_eeprom(hw, 86, 0x0); + txgbe_release_swfw_sync(hw, 1); } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 181a1df523..ef30e0c40a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -541,6 +541,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -594,6 +595,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -604,6 +607,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6518,7 +6522,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 12/13] net/txgbe: fix CR/KR link training and recovery [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 11/13] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-08-27 11:42 ` [PATCH 13/13] net/txgbe: align link capabilities and DAC classification Zaiyu Wang ` (12 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt from the event handler (50 x 1 ms poll, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++----------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 28 ++++- 6 files changed, 129 insertions(+), 69 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..f840e6b5dd 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2123,6 +2124,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2351,24 +2353,29 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2383,31 +2390,84 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2463,52 +2523,48 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + return ret; } @@ -2517,27 +2573,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2583,11 +2619,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..da0d02b79f 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u8 bp_link_mode, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index ef30e0c40a..269e0aadd9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3025,6 +3025,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3043,8 +3044,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->phy.sfp_type = txgbe_sfp_type_not_present; } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!(txgbe_xpcs_an_enabled(hw))) { + BP_LOG("%s %d\n", __func__, __LINE__); return; + } if (!hw->devarg.auto_neg) return; @@ -3063,6 +3066,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3080,7 +3084,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3783,8 +3801,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) - intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); + intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG;//aml40-to-do + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH 13/13] net/txgbe: align link capabilities and DAC classification [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 12/13] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-08-27 11:42 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 00/15] Wangxun fixes and new features Zaiyu Wang ` (11 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-08-27 11:42 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the five-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), multispeed fiber, 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). - Unify DAC classification on txgbe_is_dac_cable(), so active DACs are no longer treated as optical modules. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 71 ++++++++++++++++++++++++---- drivers/net/txgbe/base/txgbe_e56.c | 6 +-- drivers/net/txgbe/base/txgbe_phy.c | 7 +++ drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 74 insertions(+), 16 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..fe4becf198 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,8 +103,7 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { hw->devarg.auto_neg = false; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index bfb8a4bc7f..b4371921cd 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,26 +95,77 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static int txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static int txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; + PMD_DRV_LOG(DEBUG, "port[%d]hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ + *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + /* + * 10G-only DAC cable: legacy build-time AUTO=0/1 default + * mode forces AN off. DPDK equivalent: devarg.auto_neg == 0. + */ + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL && + hw->devarg.auto_neg == 0) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (hw->phy.multispeed_fiber) { + /* multispeed fiber must come before single-sfp/qsfp fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; *autoneg = true; - } else if (txgbe_is_backplane(hw)) { + } else if (txgbe_is_40g_fiber_qsfp(hw)) { *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..cc168a9f81 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -2622,8 +2621,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..e52f1da87d 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..b00f00931c 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -310,6 +310,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 00/15] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-08-27 11:42 ` [PATCH 13/13] net/txgbe: align link capabilities and DAC classification Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (10 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally refines U DP offload handling. --- v2: - add a new commit to handle 10G config on dual-speed DAC - P02: handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched. - P07: resolve the inner tunnel type in a local variable instead of rewriting mbuf->ol_flags. check the rte_pktmbuf_read() result for short or mis-annotated packets. use RTE_GENEVE_DEFAULT_PORT instead of the literal 6081. add a Fixes: tag pointing to the commit that introduced the tunnel offload handling. - P10: split into a bug-fix commit and a feature commit. document both devargs in the NIC guide and the release notes. - P11: check the acquire_swfw_sync() result and only touch I2C while the semaphore is held. replace the magic numbers with named constants. add the release notes entry. - P12: drop the stray C99 comment on the AN-config flag assignment that checkpatch rejects. - P13: reword the message to state that 40G active cables are handled through the optical path. use txgbe_is_dac_cable() in the 40G FFE selection to match the 25G path. --- --- Not changed in this revision: - P11: enable_tx_laser() is not gated by laser_off. laser_off only controls whether the Tx laser is brought down on port stop, while enable_tx_laser() is unconditionally called from dev_start() and dev_set_link_up() and must always bring the laser up, otherwise the default (laser_off=0) configuration would never bring the link up. - P11: no extra restore of PMD_CFG0 bit 1 on the DAC path. Bits 19:12 are restored by txgbe_e56_set_phy_link_mode() and txgbe_set_link_to_amlite(); bit 1 (PMD enable) is also restored by txgbe_e56_set_phy_link_mode(), which the xpcs AN path calls on link up, so no additional write is required. - P12: no total iteration bound was added to txgbe_e56_exchange_page(). The loop is bounded per page and exits when the AN FSM reaches 0x8, so it does not hang in a normal Clause 73 flow. As this is hardware related configuration, we leave the current behaviour unchanged for now. --- Zaiyu Wang (15): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: add offload support for tunnel type UDP net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 18 +++ doc/guides/rel_notes/release_26_07.rst | 8 ++ drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 100 +++++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +-- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_hw.c | 37 ++++++ drivers/net/txgbe/base/txgbe_phy.c | 13 ++ drivers/net/txgbe/base/txgbe_phy.h | 7 ++ drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 120 ++++++++++++++++-- drivers/net/txgbe/txgbe_rxtx.c | 29 ++++- 15 files changed, 437 insertions(+), 101 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260908124047.2284-1-zaiyuwang@trustnetic.com>]
* [PATCH v2 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (13 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Three checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. 3. setup_phy_link_aml40() on the AN path passed a hardcoded 40 to txgbe_e56_set_phy_link_mode(), ignoring the caller speed. Remove each of these restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 17 ++++++++++++----- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -171,11 +172,17 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4d2746371b..bc2e11e801 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1896,7 +1896,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 02/15] net/txgbe: fix e56 PHY configuration error [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> 2026-09-08 12:38 ` [PATCH v2 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (12 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 03/15] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> 2026-09-08 12:38 ` [PATCH v2 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (11 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 04/15] net/txgbe: do not force reconfig on link retry [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang ` (10 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc2e11e801..9e4eca40cf 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3286,7 +3286,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 05/15] net/txgbe: set i2c sda hold time [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (9 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 06/15] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (8 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, and include 10G in the default advertised speed mask in txgbe_dev_start() so a 10G link is reported with the correct speed. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 9e4eca40cf..bb4ff3c492 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1912,7 +1912,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 07/15] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang ` (7 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 08/15] net/txgbe: add offload support for tunnel type UDP [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit The non-standard RTE_MBUF_F_TX_TUNNEL_UDP tunnel type (UDP encapsulation carrying either VXLAN or GENEVE) is not handled: txgbe_set_xmit_ctx() falls into the "unknown tunnel type" case and txgbe_get_tun_len() cannot compute the tunnel length, so tunneled packets are sent with a wrong descriptor or dropped. Resolve RTE_MBUF_F_TX_TUNNEL_UDP by parsing the UDP destination port in a local variable instead of rewriting the mbuf: the application still owns the mbuf and may re-transmit it (cloned or multicast paths), so a second pass would otherwise see the resolved VXLAN/GENEVE type instead of UDP. The outer_l2_len/outer_l3_len used for the offset are application supplied and not validated by the driver, so check the rte_pktmbuf_read() result and fall back to a zero tunnel length on a short or mis-annotated packet. Use RTE_GENEVE_DEFAULT_PORT for the GENEVE destination port. Fixes: ca46fcd753b1 ("net/txgbe: support Tx with hardware offload") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index a295666f9d..ad90df5f69 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -21,6 +21,7 @@ #include <rte_debug.h> #include <rte_ethdev.h> #include <ethdev_driver.h> +#include <rte_geneve.h> #include <rte_security_driver.h> #include <rte_memzone.h> #include <rte_atomic.h> @@ -419,6 +420,7 @@ txgbe_set_xmit_ctx(struct txgbe_tx_queue *txq, break; case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: case RTE_MBUF_F_TX_TUNNEL_GENEVE: tunnel_seed |= TXGBE_TXD_ETYPE_UDP; break; @@ -593,6 +595,7 @@ tx_desc_ol_flags_to_ptype(uint64_t oflags) switch (oflags & RTE_MBUF_F_TX_TUNNEL_MASK) { case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: ptype |= RTE_PTYPE_TUNNEL_GRENAT; break; case RTE_MBUF_F_TX_TUNNEL_GRE: @@ -713,9 +716,32 @@ txgbe_get_tun_len(struct rte_mbuf *mbuf) const struct txgbe_genevehdr *gh; const struct txgbe_grehdr *grh; struct txgbe_grehdr grehdr; + struct txgbe_udphdr udphdr; + const struct txgbe_udphdr *uh; + uint64_t tun_type; uint8_t tun_len; - switch (mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) { + /* Resolve the UDP tunnel to its inner type without rewriting the + * mbuf: the application still owns it and may re-transmit it. + */ + tun_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK; + if (tun_type == RTE_MBUF_F_TX_TUNNEL_UDP) { + uh = rte_pktmbuf_read(mbuf, + mbuf->outer_l2_len + mbuf->outer_l3_len, + sizeof(udphdr), &udphdr); + if (uh == NULL) { + /* The outer offsets are application supplied and may + * point past the end of the packet. + */ + return 0; + } + tun_type = (uh->dest == + rte_cpu_to_be_16(RTE_GENEVE_DEFAULT_PORT)) ? + RTE_MBUF_F_TX_TUNNEL_GENEVE : + RTE_MBUF_F_TX_TUNNEL_VXLAN; + } + + switch (tun_type) { case RTE_MBUF_F_TX_TUNNEL_IPIP: tun_len = 0; break; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bb4ff3c492..0711a28a5c 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2987,6 +2987,20 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3110,10 +3124,22 @@ txgbe_dev_detect_sfp(void *param) PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the port is started, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0711a28a5c..0aa2d5719b 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2015,6 +2015,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3096,7 +3101,7 @@ txgbe_dev_detect_sfp(void *param) struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); @@ -3104,6 +3109,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3142,6 +3152,11 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + dev->data->dev_started) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang ` (3 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0aa2d5719b..afed59d4cf 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -531,6 +531,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u8 pballoc = 0; @@ -540,6 +541,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -588,6 +598,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -690,7 +708,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -698,6 +715,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 12/15] net/txgbe: add pre2 and backplane capability devargs [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The 25G E56 PHY has a second pre-cursor tap that cannot be tuned with the existing devargs: with ffe_set enabled, pre2 stays at the default value because no devarg feeds it. The advertised 40G backplane capability is hardwired to KR4+CR4, so there is no way to advertise only 40GBASE-KR4 or only 40GBASE-CR4. Add the ffe_pre2 and bp_capa device arguments. ffe_pre2 configures the E56 PHY second pre-cursor tap, bp_capa selects the backplane capability advertised on the 40G NIC, and both are documented in the NIC guide and the release notes. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 11 +++++++++++ doc/guides/rel_notes/release_26_07.rst | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..d56fb3b99a 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -142,6 +142,11 @@ Please note that following ``devargs`` are only set for backplane NICs. PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + - ``ffe_post`` (default **44**) PHY parameter used for user debugging. Setting other values to @@ -177,6 +182,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst index 3d18ba2dd0..f65044c9b9 100644 --- a/doc/guides/rel_notes/release_26_07.rst +++ b/doc/guides/rel_notes/release_26_07.rst @@ -163,6 +163,11 @@ New Features so the application can reset the VF and resume normal packet Rx/Tx. * Added VF support for the Amber-Lite 40G NIC variant, with new device IDs ``0x503f`` and ``0x513f``. + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). * **Updated Intel qat crypto driver dependency requirements.** diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index afed59d4cf..27a6ff0b2e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -540,13 +540,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -571,6 +578,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -583,6 +592,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -596,7 +607,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6498,12 +6511,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:38 ` [PATCH v2 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-08 12:39 ` [PATCH v2 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 +++++ doc/guides/rel_notes/release_26_07.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 37 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 ++++- 6 files changed, 62 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index d56fb3b99a..a580450726 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -188,6 +188,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst index f65044c9b9..4c302540d8 100644 --- a/doc/guides/rel_notes/release_26_07.rst +++ b/doc/guides/rel_notes/release_26_07.rst @@ -168,6 +168,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). * **Updated Intel qat crypto driver dependency requirements.** diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..891f1ed0c4 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,33 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (txgbe_acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + int err; + + err = hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + if (err) + DEBUGOUT("Disable Tx laser failed %d\n", err); + txgbe_release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3316,15 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (txgbe_acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + int err; + + err = hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + if (err) + DEBUGOUT("Enable Tx laser failed %d\n", err); + txgbe_release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 27a6ff0b2e..9c31b2cfed 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -541,6 +541,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -594,6 +595,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -604,6 +607,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6518,7 +6522,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 14/15] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-08 12:38 ` Zaiyu Wang 2026-09-08 12:39 ` [PATCH v2 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:38 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt from the event handler (50 x 1 ms poll, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Drop a stray C99 comment left on the AN-config flag assignment. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++----------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 26 ++++- 6 files changed, 128 insertions(+), 68 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..f840e6b5dd 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2123,6 +2124,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2351,24 +2353,29 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2383,31 +2390,84 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2463,52 +2523,48 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + return ret; } @@ -2517,27 +2573,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2583,11 +2619,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..da0d02b79f 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u8 bp_link_mode, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 9c31b2cfed..5e3403646c 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3025,6 +3025,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3043,8 +3044,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->phy.sfp_type = txgbe_sfp_type_not_present; } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!(txgbe_xpcs_an_enabled(hw))) { + BP_LOG("%s %d\n", __func__, __LINE__); return; + } if (!hw->devarg.auto_neg) return; @@ -3063,6 +3066,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3080,7 +3084,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3783,8 +3801,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 15/15] net/txgbe: align link capabilities and DAC classification [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-08 12:38 ` [PATCH v2 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-08 12:39 ` Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:39 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the five-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), multispeed fiber, 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 74 +++++++++++++++++++++++----- drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 7 +++ drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..fe4becf198 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,8 +103,7 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { hw->devarg.auto_neg = false; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..512b8ba331 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,77 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static int txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static int txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + PMD_DRV_LOG(DEBUG, "port[%d]hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + /* + * 10G-only DAC cable: legacy build-time AUTO=0/1 default + * mode forces AN off. DPDK equivalent: devarg.auto_neg == 0. + */ + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL && + hw->devarg.auto_neg == 0) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (hw->phy.multispeed_fiber) { + /* multispeed fiber must come before single-sfp/qsfp fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..e52f1da87d 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 00/15] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (14 preceding siblings ...) [not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com> @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 14:20 ` Stephen Hemminger [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (8 subsequent siblings) 24 siblings, 1 reply; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally refines UDP offload handling. --- v2: - add a new commit to handle 10G config on dual-speed DAC - P02: handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched. - P07: resolve the inner tunnel type in a local variable instead of rewriting mbuf->ol_flags. check the rte_pktmbuf_read() result for short or mis-annotated packets. use RTE_GENEVE_DEFAULT_PORT instead of the literal 6081. add a Fixes: tag pointing to the commit that introduced the tunnel offload handling. - P10: split into a bug-fix commit and a feature commit. document both devargs in the NIC guide and the release notes. - P11: check the acquire_swfw_sync() result and only touch I2C while the semaphore is held. replace the magic numbers with named constants. add the release notes entry. - P12: drop the stray C99 comment on the AN-config flag assignment that checkpatch rejects. - P13: reword the message to state that 40G active cables are handled through the optical path. use txgbe_is_dac_cable() in the 40G FFE selection to match the 25G path. --- --- Not changed in this revision: - P11: enable_tx_laser() is not gated by laser_off. laser_off only controls whether the Tx laser is brought down on port stop, while enable_tx_laser() is unconditionally called from dev_start() and dev_set_link_up() and must always bring the laser up, otherwise the default (laser_off=0) configuration would never bring the link up. - P11: no extra restore of PMD_CFG0 bit 1 on the DAC path. Bits 19:12 are restored by txgbe_e56_set_phy_link_mode() and txgbe_set_link_to_amlite(); bit 1 (PMD enable) is also restored by txgbe_e56_set_phy_link_mode(), which the xpcs AN path calls on link up, so no additional write is required. - P12: no total iteration bound was added to txgbe_e56_exchange_page(). The loop is bounded per page and exits when the AN FSM reaches 0x8, so it does not hang in a normal Clause 73 flow. As this is hardware related configuration, we leave the current behaviour unchanged for now. --- Zaiyu Wang (15): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: add offload support for tunnel type UDP net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 18 +++ doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 100 +++++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +-- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_hw.c | 29 +++++ drivers/net/txgbe/base/txgbe_phy.c | 13 ++ drivers/net/txgbe/base/txgbe_phy.h | 7 ++ drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 120 ++++++++++++++++-- drivers/net/txgbe/txgbe_rxtx.c | 29 ++++- 15 files changed, 432 insertions(+), 101 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v3 00/15] Wangxun fixes and new features 2026-09-08 13:25 ` [PATCH v3 00/15] Wangxun fixes and new features Zaiyu Wang @ 2026-09-08 14:20 ` Stephen Hemminger 0 siblings, 0 replies; 116+ messages in thread From: Stephen Hemminger @ 2026-09-08 14:20 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Tue, 8 Sep 2026 21:25:45 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs > (CR/KR training, hot-plug, 10G link state), and additionally refines UDP > offload handling. > > --- > v2: > - add a new commit to handle 10G config on dual-speed DAC > - P02: handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched. > - P07: resolve the inner tunnel type in a local variable instead of rewriting mbuf->ol_flags. > check the rte_pktmbuf_read() result for short or mis-annotated packets. > use RTE_GENEVE_DEFAULT_PORT instead of the literal 6081. > add a Fixes: tag pointing to the commit that introduced the tunnel offload handling. > - P10: split into a bug-fix commit and a feature commit. > document both devargs in the NIC guide and the release notes. > - P11: check the acquire_swfw_sync() result and only touch I2C while the semaphore is held. > replace the magic numbers with named constants. > add the release notes entry. > - P12: drop the stray C99 comment on the AN-config flag assignment that checkpatch rejects. > - P13: reword the message to state that 40G active cables are handled through the optical path. > use txgbe_is_dac_cable() in the 40G FFE selection to match the 25G path. > --- > > --- > Not changed in this revision: > > - P11: enable_tx_laser() is not gated by laser_off. laser_off only > controls whether the Tx laser is brought down on port stop, while > enable_tx_laser() is unconditionally called from dev_start() and > dev_set_link_up() and must always bring the laser up, otherwise the > default (laser_off=0) configuration would never bring the link up. > > - P11: no extra restore of PMD_CFG0 bit 1 on the DAC path. Bits 19:12 > are restored by txgbe_e56_set_phy_link_mode() and > txgbe_set_link_to_amlite(); bit 1 (PMD enable) is also restored by > txgbe_e56_set_phy_link_mode(), which the xpcs AN path calls on link > up, so no additional write is required. > > - P12: no total iteration bound was added to txgbe_e56_exchange_page(). > The loop is bounded per page and exits when the AN FSM reaches 0x8, > so it does not hang in a normal Clause 73 flow. As this is hardware > related configuration, we leave the current behaviour unchanged for > now. > --- > > Zaiyu Wang (15): > net/txgbe: fix failure to configure 10G on dual-speed DAC > net/txgbe: fix e56 PHY configuration error > net/txgbe: fix incorrect link state in 10G forced mode > net/txgbe: do not force reconfig on link retry > net/txgbe: set i2c sda hold time > net/txgbe: fix link speed display info for 10G mode > net/txgbe: remove stale outer UDP checksum offload flag > net/txgbe: add offload support for tunnel type UDP > net/txgbe: fix SFP hot-plug when auto-negotiation is on > net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation > net/txgbe: fix 40G FFE tuning applied to first lane only > net/txgbe: add pre2 and backplane capability devargs > net/txgbe: add devarg to turn off Tx laser for 40G NIC > net/txgbe: fix CR/KR link training and recovery > net/txgbe: align link capabilities and DAC classification > > doc/guides/nics/txgbe.rst | 18 +++ > doc/guides/rel_notes/release_26_11.rst | 11 ++ > drivers/net/txgbe/base/txgbe_aml.c | 3 +- > drivers/net/txgbe/base/txgbe_aml40.c | 100 +++++++++++++-- > drivers/net/txgbe/base/txgbe_e56.c | 14 +-- > drivers/net/txgbe/base/txgbe_e56.h | 6 + > drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++---------- > drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + > drivers/net/txgbe/base/txgbe_hw.c | 29 +++++ > drivers/net/txgbe/base/txgbe_phy.c | 13 ++ > drivers/net/txgbe/base/txgbe_phy.h | 7 ++ > drivers/net/txgbe/base/txgbe_regs.h | 3 + > drivers/net/txgbe/base/txgbe_type.h | 17 ++- > drivers/net/txgbe/txgbe_ethdev.c | 120 ++++++++++++++++-- > drivers/net/txgbe/txgbe_rxtx.c | 29 ++++- > 15 files changed, 432 insertions(+), 101 deletions(-) Looks good, but there are still some leftover items to address. AI is good at picking out detail but can be wrong. So dont trust it. Review of "[PATCH v3 00/15] net/txgbe: Amber-Lite link fixes, devargs" Applied cleanly on d55ccd4 ("pci: remove deprecated catch-all flag"). Reviewed against the post-apply tree. Build and checkpatch were not run for this revision. Closed since the previous revision: - The multi-bit speed mask reaching txgbe_set_link_to_amlite() and txgbe_e56_tx_ffe_cfg(), which compare with ==. Patch 01 widens allowed_speeds and adds the highest-set-bit reduction ahead of both consumers. - link_valid set true after TXGBE_ERR_PHY_INIT_NOT_DONE (patch 03). - Unchecked rte_pktmbuf_read() and the ol_flags rewrite in txgbe_get_tun_len() (patch 08); RTE_GENEVE_DEFAULT_PORT is used and the two new TUNNEL_UDP case labels are the right consequence of no longer mutating the mbuf. - The //aml40-to-do C99 comment. - Incomplete txgbe_is_dac_cable() unification (patch 15 converts the 40G branch of tx_ffe_cfg, rxs_calib_adapt_seq and the aml.c capability function as well). - Release notes, txgbe.rst entries, named constants for the SFF-8636 Tx disable byte and PMD_CFG0, and the acquire_swfw_sync return checks on the disable path (patches 12 and 13). Patch 13/15: net/txgbe: add devarg to turn off Tx laser for 40G NIC Error: the enable path is still not guarded by the devarg. This was raised on the previous revision and is unchanged: void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) { ... if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; if (hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { hw->phy.write_i2c_eeprom(hw, TXGBE_SFF_8636_TX_DISABLE, 0x0); laser_off defaults to 0 and is documented as opt-in, but this I2C EEPROM write runs on every enable_tx_laser() for every AML40 port whether or not the user asked for it. The disable path deliberately branches before touching I2C: if (hw->devarg.laser_off) { if (txgbe_is_dac_cable(hw) || hw->phy.sfp_type == txgbe_sfp_type_unknown) { ... clear PMD_CFG0 19:16, 15:12, bit 1 ... } else if (hw->mac.acquire_swfw_sync(...) == 0) { ... SFF-8636 Tx disable ... so with laser_off=1 on a DAC cable, down clears those PMD_CFG0 fields and up writes I2C to a cable that has no EEPROM Tx-disable byte to write. Please gate the enable path on hw->devarg.laser_off and mirror the DAC/QSFP branch. Warning: the disable path's "no module" case tests hw->phy.sfp_type == txgbe_sfp_type_unknown but patches 09 and 10 in this same series set hw->phy.sfp_type = txgbe_sfp_type_not_present; on module removal. Those are different enumerators (0 versus 0xFFFE), so after a pull the disable path falls into the else and issues an I2C write to an absent module instead of taking the PCS branch. Test both, or use one enumerator consistently for "no module". Patch 14/15: net/txgbe: fix CR/KR link training and recovery Error: txgbe_e56_exchange_page() can still loop indefinitely. count2 was added and is incremented on every iteration, but it is only used in a log message: BP_LOG("AN exchange page done in %d ms\n", count2); The loop bound is still reset from inside the loop body: if (rdata & BIT(15)) { wr32_epcs(hw, 0x70016, 0x2001); ... next_page = 1; count = 0; /* reset count to wait next page */ } so a link partner that keeps asserting next-page at 0x70019 keeps resetting count and the loop never terminates. This revision also moves the call out of txgbe_handle_e56_bkp_an73_flow() and into txgbe_dev_e56_check_bp_event(), so it now runs directly in the interrupt/alarm thread and a wedge there blocks every other alarm in the process. count2 is the budget that is needed; it just needs to be enforced: if (count2 >= MAX_AN_PAGE_ITERATIONS) return -ETIMEDOUT; at the top of the loop body would cap the total while still allowing count to restart per page. Info (pre-existing, not introduced by this patch): three results in txgbe_e56_cl72_training() are stored and discarded. All three lines are diff context here, so they predate the patch, but the function is being reworked so they are cheap to fix in passing: status = txgbe_set_phy_link_mode(hw, bylinkmode); /* never read */ ... status = txgbe_e56_get_temp(hw, &temp_data); /* overwritten */ ... status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); The last one is neither ORed into ret nor returned, so an adc adaptation failure is silently dropped. The removal of the early return after txgbe_e56_cl72_training() in txgbe_handle_e56_bkp_an73_flow() is fine: status is not reassigned before the return, so a training failure is still propagated and the idle-detect thresholds are now programmed either way. Patch 10/15: net/txgbe: fix DAC hot-plug on 40G NIC with autoneg Warning: the new rearm re-arms without cancelling first, so the poll chain can be duplicated: rearm: if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && dev->data->dev_started) rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); txgbe_dev_detect_sfp() is also scheduled independently by txgbe_dev_sfp_event() -- unconditionally on TXGBE_GPIOBIT_2, and again on TXGBE_GPIOBIT_4 for aml40. That invocation falls through to rearm as well and starts a second self-perpetuating 2-second chain, and each subsequent GPIO event adds another. Patch 09 handles exactly this for the other alarm, with the comment "so that only one instance of it is running at a time": rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); The same cancel is needed before the rearm set. (The dev_stop path is fine -- rte_eal_alarm_cancel() re-walks the list in a do/while until nothing matching is executing, so a re-arm issued by the executing callback is picked up on the next pass.) Patch 15/15: net/txgbe: align link capabilities and DAC classification Warning: the *autoneg the patch computes is never read. All six call sites of mac.get_link_capabilities pass a local that is not examined afterwards: txgbe_setup_phy_link_aml40(), txgbe_dev_start(), the two link alarm handlers in txgbe_ethdev.c, and both FEC ops. So the new DAC branch has no effect: if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL && hw->devarg.auto_neg == 0) { *autoneg = false; } else { *autoneg = hw->devarg.auto_neg; } It is also a no-op on its own terms: the guard already requires hw->devarg.auto_neg == 0, so the else arm yields false anyway and the whole construct reduces to *autoneg = hw->devarg.auto_neg. The 25G sibling that this is modelled on writes the field that is actually consulted: if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { hw->devarg.auto_neg = false; *autoneg = false; hw->devarg.auto_neg is what txgbe_xpcs_an_enabled() reads. If the intent is to force AN off for 10G-only DAC cables on AML40, the aml40 version needs that assignment too; otherwise the comment about the legacy AUTO=0/1 default does not describe what the code does. Info: the multispeed_fiber arm is unreachable on this MAC type. hw->phy.multispeed_fiber is only assigned in txgbe_identify_sfp_module(), and only under txgbe_mac_aml or the SP else-branch; txgbe_identify_qsfp_module() never touches it. So } else if (hw->phy.multispeed_fiber) { never runs on aml40 and the "multispeed fiber must come before single-sfp/qsfp fiber" ordering comment has nothing to order. Patch 01/15: net/txgbe: fix failure to configure 10G on dual-speed DAC Info: the third item in the commit message does not hold. The message lists as a blocker that setup_phy_link_aml40() "passed a hardcoded 40 to txgbe_e56_set_phy_link_mode(), ignoring the caller speed", but that function discards the argument: int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u8 bp_link_mode, u32 need_restart) { ... UNREFERENCED_PARAMETER(bp_link_mode); so replacing 40 with speed changes nothing. Worth also noting that the new argument is a bitmask -- TXGBE_LINK_SPEED_40GB_FULL is 0x0040 -- passed into a u8 whose other users in txgbe_e56_bp.c compare it against 10, 25 and 40. If the parameter is ever wired up, the value handed in here will be wrong. Either drop the hunk and the third bullet, or convert the speed to a link mode at the call site. Patch 09/15: net/txgbe: fix SFP hot-plug when auto-negotiation is on Info: the new module-present sampling is not gated on !txgbe_is_backplane(hw): else if (hw->mac.type == txgbe_mac_aml40) value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; if (value != 0 && hw->phy.sfp_type != txgbe_sfp_type_not_present) { PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); On a backplane AML40 port there is no module, so this reports a removal that never happened and clears sfp_type. It is harmless for the AN gate -- txgbe_xpcs_an_enabled() returns true for backplane regardless of sfp_type -- but the log is misleading. Patch 10 adds exactly the !txgbe_is_backplane(hw) guard for its own alarm; the same guard fits here. No Reviewed-by on this revision -- the two Errors above are both carried over unchanged from the previous revision. Review-Result: ERROR ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260908132742.2661-1-zaiyuwang@trustnetic.com>]
* [PATCH v3 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (13 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Three checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. 3. setup_phy_link_aml40() on the AN path passed a hardcoded 40 to txgbe_e56_set_phy_link_mode(), ignoring the caller speed. Remove each of these restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 17 ++++++++++++----- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -171,11 +172,17 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4d2746371b..bc2e11e801 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1896,7 +1896,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 02/15] net/txgbe: fix e56 PHY configuration error [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> 2026-09-08 13:25 ` [PATCH v3 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (12 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 03/15] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> 2026-09-08 13:25 ` [PATCH v3 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (11 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 04/15] net/txgbe: do not force reconfig on link retry [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang ` (10 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc2e11e801..9e4eca40cf 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3286,7 +3286,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 05/15] net/txgbe: set i2c sda hold time [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (9 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 06/15] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (8 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, and include 10G in the default advertised speed mask in txgbe_dev_start() so a 10G link is reported with the correct speed. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 9e4eca40cf..bb4ff3c492 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1912,7 +1912,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 07/15] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang ` (7 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 08/15] net/txgbe: add offload support for tunnel type UDP [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit The non-standard RTE_MBUF_F_TX_TUNNEL_UDP tunnel type (UDP encapsulation carrying either VXLAN or GENEVE) is not handled: txgbe_set_xmit_ctx() falls into the "unknown tunnel type" case and txgbe_get_tun_len() cannot compute the tunnel length, so tunneled packets are sent with a wrong descriptor or dropped. Resolve RTE_MBUF_F_TX_TUNNEL_UDP by parsing the UDP destination port in a local variable instead of rewriting the mbuf: the application still owns the mbuf and may re-transmit it (cloned or multicast paths), so a second pass would otherwise see the resolved VXLAN/GENEVE type instead of UDP. The outer_l2_len/outer_l3_len used for the offset are application supplied and not validated by the driver, so check the rte_pktmbuf_read() result and fall back to a zero tunnel length on a short or mis-annotated packet. Use RTE_GENEVE_DEFAULT_PORT for the GENEVE destination port. Fixes: ca46fcd753b1 ("net/txgbe: support Tx with hardware offload") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index a295666f9d..ad90df5f69 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -21,6 +21,7 @@ #include <rte_debug.h> #include <rte_ethdev.h> #include <ethdev_driver.h> +#include <rte_geneve.h> #include <rte_security_driver.h> #include <rte_memzone.h> #include <rte_atomic.h> @@ -419,6 +420,7 @@ txgbe_set_xmit_ctx(struct txgbe_tx_queue *txq, break; case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: case RTE_MBUF_F_TX_TUNNEL_GENEVE: tunnel_seed |= TXGBE_TXD_ETYPE_UDP; break; @@ -593,6 +595,7 @@ tx_desc_ol_flags_to_ptype(uint64_t oflags) switch (oflags & RTE_MBUF_F_TX_TUNNEL_MASK) { case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: ptype |= RTE_PTYPE_TUNNEL_GRENAT; break; case RTE_MBUF_F_TX_TUNNEL_GRE: @@ -713,9 +716,32 @@ txgbe_get_tun_len(struct rte_mbuf *mbuf) const struct txgbe_genevehdr *gh; const struct txgbe_grehdr *grh; struct txgbe_grehdr grehdr; + struct txgbe_udphdr udphdr; + const struct txgbe_udphdr *uh; + uint64_t tun_type; uint8_t tun_len; - switch (mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) { + /* Resolve the UDP tunnel to its inner type without rewriting the + * mbuf: the application still owns it and may re-transmit it. + */ + tun_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK; + if (tun_type == RTE_MBUF_F_TX_TUNNEL_UDP) { + uh = rte_pktmbuf_read(mbuf, + mbuf->outer_l2_len + mbuf->outer_l3_len, + sizeof(udphdr), &udphdr); + if (uh == NULL) { + /* The outer offsets are application supplied and may + * point past the end of the packet. + */ + return 0; + } + tun_type = (uh->dest == + rte_cpu_to_be_16(RTE_GENEVE_DEFAULT_PORT)) ? + RTE_MBUF_F_TX_TUNNEL_GENEVE : + RTE_MBUF_F_TX_TUNNEL_VXLAN; + } + + switch (tun_type) { case RTE_MBUF_F_TX_TUNNEL_IPIP: tun_len = 0; break; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bb4ff3c492..0711a28a5c 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2987,6 +2987,20 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3110,10 +3124,22 @@ txgbe_dev_detect_sfp(void *param) PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the port is started, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0711a28a5c..0aa2d5719b 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2015,6 +2015,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3096,7 +3101,7 @@ txgbe_dev_detect_sfp(void *param) struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); @@ -3104,6 +3109,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3142,6 +3152,11 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + dev->data->dev_started) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang ` (3 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0aa2d5719b..afed59d4cf 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -531,6 +531,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u8 pballoc = 0; @@ -540,6 +541,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -588,6 +598,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -690,7 +708,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -698,6 +715,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 12/15] net/txgbe: add pre2 and backplane capability devargs [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The 25G E56 PHY has a second pre-cursor tap that cannot be tuned with the existing devargs: with ffe_set enabled, pre2 stays at the default value because no devarg feeds it. The advertised 40G backplane capability is hardwired to KR4+CR4, so there is no way to advertise only 40GBASE-KR4 or only 40GBASE-CR4. Add the ffe_pre2 and bp_capa device arguments. ffe_pre2 configures the E56 PHY second pre-cursor tap, bp_capa selects the backplane capability advertised on the 40G NIC, and both are documented in the NIC guide and the release notes. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 11 +++++++++++ doc/guides/rel_notes/release_26_11.rst | 8 ++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..d56fb3b99a 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -142,6 +142,11 @@ Please note that following ``devargs`` are only set for backplane NICs. PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + - ``ffe_post`` (default **44**) PHY parameter used for user debugging. Setting other values to @@ -177,6 +182,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 87c7e81bde..822cd36d20 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -56,6 +56,14 @@ New Features ======================================================= +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index afed59d4cf..27a6ff0b2e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -540,13 +540,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -571,6 +578,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -583,6 +592,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -596,7 +607,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6498,12 +6511,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:25 ` [PATCH v3 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-08 13:26 ` [PATCH v3 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 +++++++ doc/guides/rel_notes/release_26_11.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 29 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 ++++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 ++++++- 6 files changed, 54 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index d56fb3b99a..a580450726 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -188,6 +188,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 822cd36d20..95a9552915 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -63,6 +63,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..f79439c523 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,29 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3312,11 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 27a6ff0b2e..9c31b2cfed 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -541,6 +541,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -594,6 +595,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -604,6 +607,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6518,7 +6522,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 14/15] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-08 13:25 ` Zaiyu Wang 2026-09-08 13:26 ` [PATCH v3 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt from the event handler (50 x 1 ms poll, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Drop a stray C99 comment left on the AN-config flag assignment. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++----------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 26 ++++- 6 files changed, 128 insertions(+), 68 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..f840e6b5dd 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2123,6 +2124,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2351,24 +2353,29 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2383,31 +2390,84 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2463,52 +2523,48 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + return ret; } @@ -2517,27 +2573,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2583,11 +2619,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..da0d02b79f 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u8 bp_link_mode, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 9c31b2cfed..5e3403646c 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3025,6 +3025,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3043,8 +3044,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->phy.sfp_type = txgbe_sfp_type_not_present; } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!(txgbe_xpcs_an_enabled(hw))) { + BP_LOG("%s %d\n", __func__, __LINE__); return; + } if (!hw->devarg.auto_neg) return; @@ -3063,6 +3066,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3080,7 +3084,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3783,8 +3801,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v3 15/15] net/txgbe: align link capabilities and DAC classification [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-08 13:25 ` [PATCH v3 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-08 13:26 ` Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-08 13:26 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the five-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), multispeed fiber, 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 74 +++++++++++++++++++++++----- drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 7 +++ drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..fe4becf198 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,8 +103,7 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { hw->devarg.auto_neg = false; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..512b8ba331 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,77 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static int txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static int txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + PMD_DRV_LOG(DEBUG, "port[%d]hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + /* + * 10G-only DAC cable: legacy build-time AUTO=0/1 default + * mode forces AN off. DPDK equivalent: devarg.auto_neg == 0. + */ + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL && + hw->devarg.auto_neg == 0) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (hw->phy.multispeed_fiber) { + /* multispeed fiber must come before single-sfp/qsfp fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..e52f1da87d 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 00/16] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (16 preceding siblings ...) [not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com> @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 13:35 ` Stephen Hemminger [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (6 subsequent siblings) 24 siblings, 1 reply; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally refines UDP offload handling. --- v4: - add a new commit to use the requested speed in PHY setup - P01: drop the hardcoded-speed hunk and the matching commit-message bullet. - P10: gate the SFP module-removal sampling. - P11: cancel the previous SFP-detect alarm before re-arming it. - P14: gate txgbe_enable_tx_laser_multispeed_fiber() on the DAC/QSFP branch. complete the "no module" case with txgbe_sfp_type_not_present. - P15: enforce count2 as an iteration budget in txgbe_e56_exchange_page(). propagate the return status instead of silently throwing it. - P16: re-assign hw->devarg.auto_neg. --- Zaiyu Wang (16): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: add offload support for tunnel type UDP net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: fix unset pre2 FFE tap and backplane capability net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 18 +++ doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 93 ++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 193 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ drivers/net/txgbe/base/txgbe_phy.c | 13 ++ drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 147 +++++++++++++++++-- drivers/net/txgbe/txgbe_rxtx.c | 29 +++- 15 files changed, 473 insertions(+), 118 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v4 00/16] Wangxun fixes and new features 2026-09-22 12:37 ` [PATCH v4 00/16] Wangxun fixes and new features Zaiyu Wang @ 2026-09-22 13:35 ` Stephen Hemminger 2026-09-29 11:21 ` Zaiyu Wang 0 siblings, 1 reply; 116+ messages in thread From: Stephen Hemminger @ 2026-09-22 13:35 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Tue, 22 Sep 2026 20:37:33 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs > (CR/KR training, hot-plug, 10G link state), and additionally refines UDP > offload handling. > > --- These AI comments look like the need addressing Review: [PATCH v4 00/16] net/txgbe: Amber-Lite link and offload fixes Author: Zaiyu Wang <zaiyuwang@trustnetic.com> Series applies to main; every commit builds with -Dwerror=true. Fixes: hashes resolve except the one noted in 13/16. Patch 10/16: net/txgbe: fix SFP hot-plug when auto-negotiation is on Warning: AN73 watchdog can be re-armed after dev_stop txgbe_dev_detect_sfp() now calls rte_eal_alarm_set() for txgbe_dev_e56_check_bp_event with no started check. dev_stop cancels check_bp_event first (txgbe_ethdev.c ~2121) and detect_sfp second (~2126). A detect_sfp instance running in the alarm thread between the two cancels, or one armed by a GPIO interrupt before txgbe_disable_intr(), re-arms the watchdog on a stopped port. check_bp_event re-arms itself unconditionally at "out:", so it keeps running, and after dev_close it dereferences freed port data. Patch 11 gates its own re-arm on dev->data->dev_started, but that flag is only cleared after dev_stop returns, so it does not close this window either. Cancel txgbe_dev_detect_sfp before txgbe_dev_e56_check_bp_event in dev_stop, and skip the re-arm in detect_sfp when hw->adapter_stopped is set. Patch 09/16: net/txgbe: add offload support for tunnel type UDP Warning: RTE_MBUF_F_TX_TUNNEL_UDP resolved by destination port The generic UDP tunnel flag is defined for tunnels that are not VXLAN or GENEVE. txgbe_get_tun_len() maps port 6081 to GENEVE and everything else to VXLAN, i.e. a fixed 16 byte UDP+VXLAN header. Any other UDP encapsulation gets a wrong tunnel length, so the inner checksum and TSO offsets are wrong, and GENEVE on a non-default port loses its options length. Since the driver advertises RTE_ETH_TX_OFFLOAD_UDP_TNL_TSO, either reject tunnels it cannot size in txgbe_prep_pkts() or stop advertising the capability. Info: the new rte_pktmbuf_read() NULL check is right, but the GRE and GENEVE cases in the same switch still dereference grh and gh without one. Same fix, same function. Patch 13/16: net/txgbe: fix unset pre2 FFE tap and backplane capability Warning: Fixes: 6104fd11089d does not exist. The 25G commit is 6104fd11086e, as used in 05/16 and 12/16. Warning: this is a feature, not a fix The recommended pre2 values are S25G_TX_FFE_CFG_DAC_PRE2 = 0x0 and S40G_TX_FFE_CFG_PRE2 = 0x0, so programming ffe_pre2 = 0 was never wrong. bp_capa = 0 is the existing KR4+CR4 behaviour. What remains is two new devargs, which do not belong in stable. Drop the Fixes tags and Cc: stable. The patch also changes the ffe_main/pre/post defaults on the 25G MAC from 27/8/44 to 0x2a/0x03/0x11. Neither the commit message nor txgbe.rst mentions this; the guide still documents 27, 8 and 44. Info: bp_capa is not range checked. Any value above 2 advertises no 40G ability at all on the 40G backplane. Patch 16/16: net/txgbe: align link capabilities and DAC classification Warning: get_link_capabilities_aml40() clears hw->devarg.auto_neg For a DAC whose fiber_suppport_speed is 10G only, the new DAC branch writes hw->devarg.auto_neg = false. Nothing sets it back. With the hot-plug support in 10/16 and 11/16, replacing that module with a 40G QSFP DAC leaves txgbe_xpcs_an_enabled() false, so AN73 never runs until the port is re-probed. The aml function has the same pattern, but hot-plug now makes it reachable on aml40. Return *autoneg = false without touching the devarg. Info: PMD_DRV_LOG in base/txgbe_aml40.c; base code uses DEBUGOUT. txgbe_is_40g_fiber_qsfp() and txgbe_is_10g_fiber_sfp() return int with true/false; make them bool. Patch 02/16: net/txgbe: use the requested speed in E56 AN setup Info: default AN advertisement changes. With dev_start passing 10G|25G (aml) or 10G|40G (aml40 after 07/16), the backplane branch now advertises 10GBASE-KR on the 25G and 40G parts, where previously it advertised only 25G or only 40G. Say so in the commit message. Patch 07/16: net/txgbe: fix link speed display info for 10G mode Info: adding 10G to the aml40 autoneg speed mask is not needed for the reported speed; that comes from the new PORTSTAT check. It changes what is advertised (see 02/16) and belongs with 01/16. Patch 15/16: net/txgbe: fix CR/KR link training and recovery Info: the CL72 poll (400 x 1 ms) and the page exchange (up to 200 x 1 ms) busy-wait inside txgbe_dev_e56_check_bp_event(), which runs on the EAL interrupt thread. This stalls interrupt and alarm handling for all ports. Info: BP_LOG expands to RTE_LOG, so its arguments are evaluated even when the log type is disabled. txgbe_e56_get_txffe() and the new "an_int" arguments do a dozen PHY reads per call only for logging. The BP_LOG("%s %d\n", __func__, __LINE__) in check_bp_event is a leftover debug line. ^ permalink raw reply [flat|nested] 116+ messages in thread
* RE: [PATCH v4 00/16] Wangxun fixes and new features 2026-09-22 13:35 ` Stephen Hemminger @ 2026-09-29 11:21 ` Zaiyu Wang 0 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:21 UTC (permalink / raw) To: 'Stephen Hemminger'; +Cc: dev, dev > -----Original Message----- > From: Stephen Hemminger <stephen@networkplumber.org> > Sent: Tuesday, September 22, 2026 9:35 PM > To: Zaiyu Wang <zaiyuwang@trustnetic.com>; Zaiyu Wang <zaiyuwang@trustnetic.com> > Cc: dev@dpdk.org; dev@dpdk.org > Subject: Re: [PATCH v4 00/16] Wangxun fixes and new features > > On Tue, 22 Sep 2026 20:37:33 +0800 > Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > > > This series addresses link-related issues on Wangxun Amber-lite > > 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and > > additionally refines UDP offload handling. > > > > --- > > These AI comments look like the need addressing > > Review: [PATCH v4 00/16] net/txgbe: Amber-Lite link and offload fixes > Author: Zaiyu Wang <zaiyuwang@trustnetic.com> > > Series applies to main; every commit builds with -Dwerror=true. > Fixes: hashes resolve except the one noted in 13/16. > Hi Stephen, Thank you for review. I have addressed these comments and sent v5 to the community. Best regards, Zaiyu ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260922125414.3638-1-zaiyuwang@trustnetic.com>]
* [PATCH v4 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (14 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4d2746371b..bc2e11e801 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1896,7 +1896,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 02/16] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> 2026-09-22 12:37 ` [PATCH v4 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (13 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, as the base layer of the out-of-tree driver does: gate the 10G and 25G advertisement on speed, keep the 40G case on the device id, and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), as the base layer does, and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++--- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..7b8af0638d 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if ((hw->device_id & 0xFF) == 0x40) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc2e11e801..69c94992ae 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1936,6 +1936,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -3017,7 +3031,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -3032,7 +3046,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -3041,7 +3056,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 03/16] net/txgbe: fix e56 PHY configuration error [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> 2026-09-22 12:37 ` [PATCH v4 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (12 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 04/16] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (11 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 05/16] net/txgbe: do not force reconfig on link retry [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang ` (10 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 69c94992ae..cb2a169da1 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3302,7 +3302,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 06/16] net/txgbe: set i2c sda hold time [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (9 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 07/16] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (8 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, and include 10G in the default advertised speed mask in txgbe_dev_start() so a 10G link is reported with the correct speed. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index cb2a169da1..626015fae2 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1912,7 +1912,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 08/16] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 09/16] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang ` (7 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 09/16] net/txgbe: add offload support for tunnel type UDP [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 10/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit The non-standard RTE_MBUF_F_TX_TUNNEL_UDP tunnel type (UDP encapsulation carrying either VXLAN or GENEVE) is not handled: txgbe_set_xmit_ctx() falls into the "unknown tunnel type" case and txgbe_get_tun_len() cannot compute the tunnel length, so tunneled packets are sent with a wrong descriptor or dropped. Resolve RTE_MBUF_F_TX_TUNNEL_UDP by parsing the UDP destination port in a local variable instead of rewriting the mbuf: the application still owns the mbuf and may re-transmit it (cloned or multicast paths), so a second pass would otherwise see the resolved VXLAN/GENEVE type instead of UDP. The outer_l2_len/outer_l3_len used for the offset are application supplied and not validated by the driver, so check the rte_pktmbuf_read() result and fall back to a zero tunnel length on a short or mis-annotated packet. Use RTE_GENEVE_DEFAULT_PORT for the GENEVE destination port. Fixes: ca46fcd753b1 ("net/txgbe: support Tx with hardware offload") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index a295666f9d..ad90df5f69 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -21,6 +21,7 @@ #include <rte_debug.h> #include <rte_ethdev.h> #include <ethdev_driver.h> +#include <rte_geneve.h> #include <rte_security_driver.h> #include <rte_memzone.h> #include <rte_atomic.h> @@ -419,6 +420,7 @@ txgbe_set_xmit_ctx(struct txgbe_tx_queue *txq, break; case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: case RTE_MBUF_F_TX_TUNNEL_GENEVE: tunnel_seed |= TXGBE_TXD_ETYPE_UDP; break; @@ -593,6 +595,7 @@ tx_desc_ol_flags_to_ptype(uint64_t oflags) switch (oflags & RTE_MBUF_F_TX_TUNNEL_MASK) { case RTE_MBUF_F_TX_TUNNEL_VXLAN: case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: + case RTE_MBUF_F_TX_TUNNEL_UDP: ptype |= RTE_PTYPE_TUNNEL_GRENAT; break; case RTE_MBUF_F_TX_TUNNEL_GRE: @@ -713,9 +716,32 @@ txgbe_get_tun_len(struct rte_mbuf *mbuf) const struct txgbe_genevehdr *gh; const struct txgbe_grehdr *grh; struct txgbe_grehdr grehdr; + struct txgbe_udphdr udphdr; + const struct txgbe_udphdr *uh; + uint64_t tun_type; uint8_t tun_len; - switch (mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) { + /* Resolve the UDP tunnel to its inner type without rewriting the + * mbuf: the application still owns it and may re-transmit it. + */ + tun_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK; + if (tun_type == RTE_MBUF_F_TX_TUNNEL_UDP) { + uh = rte_pktmbuf_read(mbuf, + mbuf->outer_l2_len + mbuf->outer_l3_len, + sizeof(udphdr), &udphdr); + if (uh == NULL) { + /* The outer offsets are application supplied and may + * point past the end of the packet. + */ + return 0; + } + tun_type = (uh->dest == + rte_cpu_to_be_16(RTE_GENEVE_DEFAULT_PORT)) ? + RTE_MBUF_F_TX_TUNNEL_GENEVE : + RTE_MBUF_F_TX_TUNNEL_VXLAN; + } + + switch (tun_type) { case RTE_MBUF_F_TX_TUNNEL_IPIP: tun_len = 0; break; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 10/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 09/16] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 11/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 626015fae2..e7f8234146 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3001,6 +3001,23 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3126,10 +3143,22 @@ txgbe_dev_detect_sfp(void *param) PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 11/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 10/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 12/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the port is started, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index e7f8234146..cd7b40dbdb 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2029,6 +2029,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3115,7 +3120,7 @@ txgbe_dev_detect_sfp(void *param) struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); @@ -3123,6 +3128,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3161,6 +3171,13 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + dev->data->dev_started) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 12/16] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 11/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 13/16] net/txgbe: fix unset pre2 FFE tap and backplane capability Zaiyu Wang ` (3 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index cd7b40dbdb..b27a5af062 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -531,6 +531,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u8 pballoc = 0; @@ -540,6 +541,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -588,6 +598,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -690,7 +708,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -698,6 +715,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 13/16] net/txgbe: fix unset pre2 FFE tap and backplane capability [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 12/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 14/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The second pre-cursor tap of the 25G E56 PHY and the advertised 40G backplane capability selector were both added without any value ever being assigned, so hw->phy.ffe_pre2 and hw->phy.bp_capa stayed at zero: - With ffe_set enabled, txgbe_e56_tx_ffe_cfg() programmed a zero second pre-cursor tap instead of the recommended value for the module. - txgbe_e56_set_phy_link_mode() could only advertise KR4+CR4: the KR4-only and CR4-only capabilities selected by bp_capa were unreachable. Assign the recommended defaults and add the ffe_pre2 and bp_capa device arguments so that both can be configured. The NIC guide and the release notes document the two new devargs. Fixes: 6104fd11089d ("net/txgbe: fix link stability for 25G NIC") Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 11 +++++++++++ doc/guides/rel_notes/release_26_11.rst | 8 ++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..d56fb3b99a 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -142,6 +142,11 @@ Please note that following ``devargs`` are only set for backplane NICs. PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + - ``ffe_post`` (default **44**) PHY parameter used for user debugging. Setting other values to @@ -177,6 +182,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 4b3e5d995c..461e26459b 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -56,6 +56,14 @@ New Features ======================================================= +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index b27a5af062..72264befae 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -540,13 +540,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -571,6 +578,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -583,6 +592,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -596,7 +607,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6519,12 +6532,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 14/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 13/16] net/txgbe: fix unset pre2 FFE tap and backplane capability Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 15/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 16/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 +++++- 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index d56fb3b99a..a580450726 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -188,6 +188,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 461e26459b..a776c4be92 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -63,6 +63,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 72264befae..90072f6e5e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -541,6 +541,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -594,6 +595,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -604,6 +607,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6539,7 +6543,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 15/16] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 14/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 2026-09-22 12:37 ` [PATCH v4 16/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt from the event handler (50 x 1 ms poll, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Drop a stray C99 comment left on the AN-config flag assignment. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 170 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 26 +++- 6 files changed, 137 insertions(+), 68 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 7b8af0638d..7c94a97e27 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,31 +2395,84 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2436,6 +2502,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2529,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2581,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2627,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 90072f6e5e..0d58b2085c 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3039,6 +3039,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3060,8 +3061,10 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!(txgbe_xpcs_an_enabled(hw))) { + BP_LOG("%s %d\n", __func__, __LINE__); return; + } if (!hw->devarg.auto_neg) return; @@ -3080,6 +3083,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3097,7 +3101,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3804,8 +3822,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v4 16/16] net/txgbe: align link capabilities and DAC classification [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> ` (14 preceding siblings ...) 2026-09-22 12:37 ` [PATCH v4 15/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-22 12:37 ` Zaiyu Wang 15 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-22 12:37 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the four-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 3 +- drivers/net/txgbe/base/txgbe_aml40.c | 65 +++++++++++++++++++++++----- drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 7 +++ drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 67 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..fe4becf198 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,8 +103,7 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { hw->devarg.auto_neg = false; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..92c2180301 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,68 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static int txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static int txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + PMD_DRV_LOG(DEBUG, "port[%d]hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + hw->devarg.auto_neg = false; + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..e52f1da87d 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 00/15] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (18 preceding siblings ...) [not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com> @ 2026-09-29 11:18 ` Zaiyu Wang [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (4 subsequent siblings) 24 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). --- v5: - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP tunnel, so the tunnel type cannot be resolved from the destination port. - P02: advertise 10G, 25G, and 40G from the requested speed mask instead of the device ID, so the 25G and 40G parts advertise 10G by default as well. - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; the AML40 default 10G|40G advertisement change is now in P02. - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port flag that dev_stop clears before the first cancel. cancel SFP detection before the watchdog. - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite FFE defaults. - P14: bound the AN page exchange, propagate its timeout to the watchdog h andler, and avoid register reads used only by disabled BP debug logs. - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; derive the effective AN73 state from the current module capabilities instead. Classify 40G active cables through the optical path, unify DAC checks on txgbe_is_dac_cable(). Not handled in this revision: - P12: bp_capa is not range-checked. Devarg validation will be added in a separate change so all txgbe devargs can be handled consistently. - P14: the AN page exchange still busy-waits on the alarm thread and can delay handling for other ports. A later change will decouple negotiation from the alarm callback and run per-port negotiations in parallel. --- Zaiyu Wang (15): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 FFE tap and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 25 +++- doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 92 ++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 25 +++- drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 178 ++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_rxtx.c | 1 - 17 files changed, 502 insertions(+), 128 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260929112119.4516-1-zaiyuwang@trustnetic.com>]
* [PATCH v5 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (13 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4d2746371b..bc2e11e801 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1896,7 +1896,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 02/15] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> 2026-09-29 11:18 ` [PATCH v5 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (12 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, as the base layer of the out-of-tree driver does: gate the 10G, 25G, and 40G advertisement on the requested speed and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. Both Amber-Lite MACs support 10GBASE-KR in addition to their nominal speed: the capability masks already report 10G|25G for the 25G MAC and 10G|40G for the 40G MAC, while the AN base page advertised exactly one speed picked from the device id. With automatic speed selection asking for 10G|40G on the 40G MAC as it already did 10G|25G on the 25G MAC, the base page advertises 10GBASE-KR together with 25GBASE-KR/CR on the 25G MAC and together with 40GBASE-KR4/CR4 on the 40G MAC. Explicit speed requests advertise only the requested modes. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), as the base layer does, and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 25 +++++++++++++++++++++---- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..760101a05e 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc2e11e801..ae15c0f440 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1912,7 +1912,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); @@ -1936,6 +1937,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -3017,7 +3032,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -3032,7 +3047,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -3041,7 +3057,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 03/15] net/txgbe: fix e56 PHY configuration error [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> 2026-09-29 11:18 ` [PATCH v5 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (11 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 04/15] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (10 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 05/15] net/txgbe: do not force reconfig on link retry [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang ` (9 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index ae15c0f440..c50f7df9ed 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3303,7 +3303,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 06/15] net/txgbe: set i2c sda hold time [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (8 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 07/15] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (7 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, so a 10G link is reported as 10G. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 08/15] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. The SFP detection alarm and the AN73 watchdog are gated on a per-port flag that txgbe_dev_start() sets before the alarms are armed and txgbe_dev_stop() clears before it cancels anything, so a handler already running on the alarm thread can neither re-arm itself nor arm the other one on a port that is being stopped. The flag goes low before the cancels because hw->adapter_stopped is only set at the end of txgbe_dev_stop(). The link thread can arm the AML link alarm while txgbe_dev_stop() waits for it, so cancel that alarm again after the thread has been joined. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 61 ++++++++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 ++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index c50f7df9ed..c41d48437a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1743,6 +1743,7 @@ txgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, static int txgbe_dev_start(struct rte_eth_dev *dev) { + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct txgbe_hw_stats *hw_stats = TXGBE_DEV_STATS(dev); struct txgbe_vf_info *vfinfo = *TXGBE_DEV_VFDATA(dev); @@ -2018,6 +2019,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_dev_rxq_interrupt_setup(dev); /* enable uio/vfio intr/eventfd mapping */ + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 1, + rte_memory_order_release); rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ @@ -2075,15 +2078,22 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 0, + rte_memory_order_release); + + /* Stop the producer before the watchdog it can arm. */ + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_check_aml_temp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); } - rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); /* disable interrupts */ txgbe_disable_intr(hw); @@ -2992,6 +3002,7 @@ void txgbe_dev_check_aml_temp_event(void *param) void txgbe_dev_e56_check_bp_event(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 an_int1 = 0, value = 0, fsm = 0; u32 __rte_unused an_int = 0; @@ -3001,6 +3012,27 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3088,7 +3120,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->bp_event_interval = 2000 * 1000; out: - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0 && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); } @@ -3096,10 +3131,15 @@ static void txgbe_dev_detect_sfp(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; s32 err; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { @@ -3122,14 +3162,31 @@ txgbe_dev_detect_sfp(void *param) err = hw->phy.identify_sfp(hw); out: + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (!hw->adapter_stopped && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index c32c61d8bf..607c3391c0 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -378,6 +378,8 @@ struct txgbe_adapter { uint8_t rss_reta_updated; RTE_ATOMIC(uint32_t) link_thread_running; + /* SFP detection and AN73 watchdog alarm state. */ + RTE_ATOMIC(uint32_t) sfp_an_alarm_enabled; rte_thread_t link_thread_tid; }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the SFP/AN73 alarm gate is set, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index c41d48437a..7481d45bf6 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2032,6 +2032,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3134,7 +3139,7 @@ txgbe_dev_detect_sfp(void *param) struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, rte_memory_order_acquire) == 0) @@ -3146,6 +3151,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3189,6 +3199,14 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang ` (3 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 7481d45bf6..e130f72ae0 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -531,6 +531,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u8 pballoc = 0; @@ -540,6 +541,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -588,6 +598,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -690,7 +708,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -698,6 +715,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The Amber-Lite E56 PHY has per-MAC FFE defaults that differ from the Sapphire defaults. In particular, the second pre-cursor tap defaults to zero, but callers need a devarg to override it when ffe_set is enabled. Add ffe_pre2 for the E56 second pre-cursor tap, and bp_capa for the 40G backplane advertisement selection. The latter supports the existing default of both KR4 and CR4, or either capability alone. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 18 +++++++++++++++--- doc/guides/rel_notes/release_26_11.rst | 8 ++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..61766cc4ac 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -132,17 +132,23 @@ Please note that following ``devargs`` are only set for backplane NICs. If disabled, the FFE parameters will not take effect. Otherwise, set 1 for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. -- ``ffe_main`` (default **27**) +- ``ffe_main`` (default **42** on the 25G Amber-Lite, **43** on the 40G + Amber-Lite, **27** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_pre`` (default **8**) +- ``ffe_pre`` (default **3** on Amber-Lite, **8** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_post`` (default **44**) +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **17** on Amber-Lite, **44** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. @@ -177,6 +183,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 4b3e5d995c..461e26459b 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -56,6 +56,14 @@ New Features ======================================================= +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index e130f72ae0..53487b5b8d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -540,13 +540,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -571,6 +578,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -583,6 +592,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -596,7 +607,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6548,12 +6561,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 +++++- 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 61766cc4ac..6aa6d4597f 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -189,6 +189,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 461e26459b..a776c4be92 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -63,6 +63,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 53487b5b8d..7d07be93ed 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -541,6 +541,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -594,6 +595,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -604,6 +607,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6568,7 +6572,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 14/15] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 2026-09-29 11:18 ` [PATCH v5 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt (1 ms step, 50-count round, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Avoid register reads that are only used by disabled BP debug logs, and drop a leftover debug line in the watchdog. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 173 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 24 +++- 7 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 760101a05e..8597e42dfd 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,31 +2395,87 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) + return; + + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2436,6 +2505,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2532,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2584,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2630,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index da069e94f6..83fee14d12 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -31,10 +31,14 @@ extern int txgbe_logtype_bp; #define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp #define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) + do { \ + if (rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) \ + RTE_LOG(DEBUG, TXGBE_BP, \ + "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ + usec_stamp() / 1000000, \ + usec_stamp() % 1000000, \ + __func__, __LINE__, ## __VA_ARGS__); \ + } while (0) #define ASSERT(x) do { \ if (!(x)) \ diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 7d07be93ed..dd9dc9a373 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3050,6 +3050,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3075,7 +3076,7 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!txgbe_xpcs_an_enabled(hw)) return; if (!hw->devarg.auto_neg) @@ -3095,6 +3096,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3112,7 +3114,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3833,8 +3849,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v5 15/15] net/txgbe: align link capabilities and DAC classification [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-29 11:18 ` [PATCH v5 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-29 11:18 ` Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 11:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the four-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN. The XPCS AN gate queries the current link capabilities, so a subsequently hot-plugged AN-capable DAC is re-evaluated and can enable AN73 again. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 64 ++++++++++++++++++++++------ drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 19 ++++++++- drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 77 insertions(+), 22 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..f3d7c9f04a 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,11 +103,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { - hw->devarg.auto_neg = false; *autoneg = false; } else { *autoneg = true; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..f0456341a7 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,67 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static bool txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static bool txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + DEBUGOUT("port[%d] hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..11d38db4ba 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); @@ -2421,10 +2428,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw) int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) { + u32 speed; + bool autoneg; + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) return false; - return hw->devarg.auto_neg ? true : false; + if (!hw->devarg.auto_neg) + return false; + + /* Re-evaluate AN support for the currently detected module. */ + if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0) + return false; + + return autoneg; } /** diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 00/15] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (20 preceding siblings ...) [not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com> @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 16:05 ` Stephen Hemminger [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (2 subsequent siblings) 24 siblings, 1 reply; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). --- v6: - fix the apply failure. --- v5: - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP tunnel, so the tunnel type cannot be resolved from the destination port. - P02: advertise 10G, 25G, and 40G from the requested speed mask instead of the device ID, so the 25G and 40G parts advertise 10G by default as well. - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; the AML40 default 10G|40G advertisement change is now in P02. - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port flag that dev_stop clears before the first cancel. cancel SFP detection before the watchdog. - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite FFE defaults. - P14: bound the AN page exchange, propagate its timeout to the watchdog h andler, and avoid register reads used only by disabled BP debug logs. - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; derive the effective AN73 state from the current module capabilities instead. Classify 40G active cables through the optical path, unify DAC checks on txgbe_is_dac_cable(). Not handled in this revision: - P12: bp_capa is not range-checked. Devarg validation will be added in a separate change so all txgbe devargs can be handled consistently. - P14: the AN page exchange still busy-waits on the alarm thread and can delay handling for other ports. A later change will decouple negotiation from the alarm callback and run per-port negotiations in parallel. --- Zaiyu Wang (15): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 FFE tap and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 25 +++- doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 92 ++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 25 +++- drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 178 ++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_rxtx.c | 1 - 17 files changed, 502 insertions(+), 128 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v6 00/15] Wangxun fixes and new features 2026-09-29 13:04 ` [PATCH v6 00/15] Wangxun fixes and new features Zaiyu Wang @ 2026-09-29 16:05 ` Stephen Hemminger 2026-09-30 10:22 ` Zaiyu Wang 0 siblings, 1 reply; 116+ messages in thread From: Stephen Hemminger @ 2026-09-29 16:05 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Tue, 29 Sep 2026 21:04:31 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs > (CR/KR training, hot-plug, 10G link state). > > --- > v6: > - fix the apply failure. > --- > v5: > - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP > tunnel, so the tunnel type cannot be resolved from the destination port. > - P02: advertise 10G, 25G, and 40G from the requested speed mask instead > of the device ID, so the 25G and 40G parts advertise 10G by > default as well. > - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; > the AML40 default 10G|40G advertisement change is now in P02. > - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port > flag that dev_stop clears before the first cancel. > cancel SFP detection before the watchdog. > - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. > - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; > drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite > FFE defaults. > - P14: bound the AN page exchange, propagate its timeout to the watchdog h > andler, and avoid register reads used only by disabled BP debug logs. > - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; > derive the effective AN73 state from the current module capabilities > instead. Classify 40G active cables through the optical path, unify > DAC checks on txgbe_is_dac_cable(). > > Not handled in this revision: > > - P12: bp_capa is not range-checked. Devarg validation will be added in a > separate change so all txgbe devargs can be handled consistently. > - P14: the AN page exchange still busy-waits on the alarm thread and can > delay handling for other ports. A later change will decouple negotiation > from the alarm callback and run per-port negotiations in parallel. > --- > > > Zaiyu Wang (15): > net/txgbe: fix failure to configure 10G on dual-speed DAC > net/txgbe: use the requested speed in E56 AN setup > net/txgbe: fix e56 PHY configuration error > net/txgbe: fix incorrect link state in 10G forced mode > net/txgbe: do not force reconfig on link retry > net/txgbe: set i2c sda hold time > net/txgbe: fix link speed display info for 10G mode > net/txgbe: remove stale outer UDP checksum offload flag > net/txgbe: fix SFP hot-plug when auto-negotiation is on > net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation > net/txgbe: fix 40G FFE tuning applied to first lane only > net/txgbe: add pre2 FFE tap and backplane capability devargs > net/txgbe: add devarg to turn off Tx laser for 40G NIC > net/txgbe: fix CR/KR link training and recovery > net/txgbe: align link capabilities and DAC classification > > doc/guides/nics/txgbe.rst | 25 +++- > doc/guides/rel_notes/release_26_11.rst | 11 ++ > drivers/net/txgbe/base/txgbe_aml.c | 4 +- > drivers/net/txgbe/base/txgbe_aml40.c | 92 ++++++++++-- > drivers/net/txgbe/base/txgbe_e56.c | 14 +- > drivers/net/txgbe/base/txgbe_e56.h | 6 + > drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++++---------- > drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- > drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ > drivers/net/txgbe/base/txgbe_osdep.h | 12 +- > drivers/net/txgbe/base/txgbe_phy.c | 25 +++- > drivers/net/txgbe/base/txgbe_phy.h | 7 + > drivers/net/txgbe/base/txgbe_regs.h | 3 + > drivers/net/txgbe/base/txgbe_type.h | 17 ++- > drivers/net/txgbe/txgbe_ethdev.c | 178 ++++++++++++++++++++-- > drivers/net/txgbe/txgbe_ethdev.h | 2 + > drivers/net/txgbe/txgbe_rxtx.c | 1 - > 17 files changed, 502 insertions(+), 128 deletions(-) Looks OK to me, AI did find a couple typos that you should fix: Reviewed the whole v6 series applied on top of main. All 15 patches apply cleanly, net/txgbe builds with no new warnings, and I found no correctness bugs. Three Info-level nits below, all in 14/15. 14/15 net/txgbe: fix CR/KR link training and recovery A typo regression in a log string the patch rewrites: BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", "TRAINNING" should be "TRAINING". The line it replaces spelled it correctly ("KR TRAINING CHECK = %x, %s. ..."), so this loses the old string for anyone grepping logs. checkpatch flags it as TYPO_SPELLING. Declarations after a statement in the new txgbe_e56_get_txffe(): if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) return; /* 21. read txffe to check kr training status */ u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; This compiles, but the rest of txgbe_e56_bp.c declares at the top of the block. Hoisting the declaration above the early return would match the file. Stale comment on the page-exchange loop: /* 50ms timeout */ for (count = 0; count < 50; count++) { count is reset to 0 each time a next page arrives, so the loop is really bounded by count2 against AN_PAGE_EXCHANGE_TIMEOUT_MS (200). The comment describes the per-round budget, not the loop bound. Review-Result: CLEAN --- Notes on things that looked suspicious but check out, recorded so they do not get re-reviewed: - 02/15: the "readers fall back to get_link_capabilities() when the field is zero" claim in the commit message is accurate -- both readers do "speed = hw->phy.autoneg_advertised; if (!speed) ...get_link_capabilities()". - 06/15: wr32m(hw, TXGBE_I2C_SDA_HOLD, ..., 0x640064) against masks 0xff0000 / 0xffff places 0x64 correctly in both the RX and TX fields. - 08/15: no remaining RTE_MBUF_F_TX_OUTER_UDP_CKSUM reference anywhere in the driver, so dropping it from TXGBE_TX_OFFLOAD_MASK is complete. - 11/15: moving txgbe_parse_devargs() after txgbe_init_shared_code() is safe -- the latter only sets the MAC type and the ops tables and reads no devarg. The four-lane FFE value reaches the register whole through wr32_ephy(), so widening the fields to u32 is what makes the replication work. - 14/15: removing the "if (status) return status;" after txgbe_e56_cl72_training() does not swallow the error -- status is not reassigned through the idle-detect writes and is still returned, and the caller checks ret. The commit message says the non-abort is deliberate. - 15/15: txgbe_xpcs_an_enabled() calling get_link_capabilities() does not recurse (no capability function calls back into it), and the !hw->devarg.auto_neg early return keeps the 25G path's unconditional *autoneg = true from re-enabling AN against the devarg. - 09/15 and 14/15 are the two patches checkpatch rejects, both on false positives: "no space after cast" on RTE_ATOMIC(uint32_t), and COMPLEX_MACRO on "#define ...CFG_0 1, 0", which is the bitfield-pair convention used throughout the e56 headers. One design point worth a second opinion rather than a fix: in 10/15, txgbe_dev_detect_sfp() re-arms itself at the "rearm:" label, which the two sfp_an_alarm_enabled == 0 early returns deliberately skip. That is how the poll stops on dev_stop, and it is correct, but it does make that gate the only thing terminating the 2-second poll that 40G hot-plug detection now depends on. ^ permalink raw reply [flat|nested] 116+ messages in thread
* RE: [PATCH v6 00/15] Wangxun fixes and new features 2026-09-29 16:05 ` Stephen Hemminger @ 2026-09-30 10:22 ` Zaiyu Wang 0 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:22 UTC (permalink / raw) To: 'Stephen Hemminger'; +Cc: dev, dev > Looks OK to me, AI did find a couple typos that you should fix: > > > Reviewed the whole v6 series applied on top of main. All 15 patches apply cleanly, net/txgbe builds with no new warnings, and I found no > correctness bugs. Three Info-level nits below, all in 14/15. > > One design point worth a second opinion rather than a fix: in 10/15, > txgbe_dev_detect_sfp() re-arms itself at the "rearm:" label, which the two sfp_an_alarm_enabled == 0 early returns deliberately skip. That is > how the poll stops on dev_stop, and it is correct, but it does make that gate the only thing terminating the 2-second poll that 40G hot-plug > detection now depends on. > Hi Stephen, Thank you for the review. I have fixed the issues you mentioned and sent v7. I also confirmed the design of the AML40 module poll. The persistent 2-second poll is intentional for AML40 non-backplane ports. These devices may not deliver module insertion or removal GPIO events, so polling must continue whether a module is absent, present, or already identified. Therefore the poll is intended to run for the lifetime of a started port and to stop only when the port is stopped. Best regards, Zaiyu ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260929130611.4871-1-zaiyuwang@trustnetic.com>]
* [PATCH v6 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (13 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0734a1c63c..d4c635dc2f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1848,7 +1848,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 02/15] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> 2026-09-29 13:04 ` [PATCH v6 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (12 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, as the base layer of the out-of-tree driver does: gate the 10G, 25G, and 40G advertisement on the requested speed and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. Both Amber-Lite MACs support 10GBASE-KR in addition to their nominal speed: the capability masks already report 10G|25G for the 25G MAC and 10G|40G for the 40G MAC, while the AN base page advertised exactly one speed picked from the device id. With automatic speed selection asking for 10G|40G on the 40G MAC as it already did 10G|25G on the 25G MAC, the base page advertises 10GBASE-KR together with 25GBASE-KR/CR on the 25G MAC and together with 40GBASE-KR4/CR4 on the 40G MAC. Explicit speed requests advertise only the requested modes. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), as the base layer does, and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 25 +++++++++++++++++++++---- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..760101a05e 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index d4c635dc2f..2f59b0794f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1864,7 +1864,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); @@ -1888,6 +1889,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -2951,7 +2966,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -2966,7 +2981,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -2975,7 +2991,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 03/15] net/txgbe: fix e56 PHY configuration error [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> 2026-09-29 13:04 ` [PATCH v6 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (11 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 04/15] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (10 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 05/15] net/txgbe: do not force reconfig on link retry [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang ` (9 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 2f59b0794f..a5ef0b3e54 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3237,7 +3237,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 06/15] net/txgbe: set i2c sda hold time [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (8 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 07/15] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (7 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, so a 10G link is reported as 10G. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 08/15] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. The SFP detection alarm and the AN73 watchdog are gated on a per-port flag that txgbe_dev_start() sets before the alarms are armed and txgbe_dev_stop() clears before it cancels anything, so a handler already running on the alarm thread can neither re-arm itself nor arm the other one on a port that is being stopped. The flag goes low before the cancels because hw->adapter_stopped is only set at the end of txgbe_dev_stop(). The link thread can arm the AML link alarm while txgbe_dev_stop() waits for it, so cancel that alarm again after the thread has been joined. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 61 ++++++++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 ++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index a5ef0b3e54..83ef9d8bfc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1695,6 +1695,7 @@ txgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, static int txgbe_dev_start(struct rte_eth_dev *dev) { + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct txgbe_hw_stats *hw_stats = TXGBE_DEV_STATS(dev); struct txgbe_vf_info *vfinfo = *TXGBE_DEV_VFDATA(dev); @@ -1970,6 +1971,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_dev_rxq_interrupt_setup(dev); /* enable uio/vfio intr/eventfd mapping */ + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 1, + rte_memory_order_release); rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ @@ -2027,15 +2030,22 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 0, + rte_memory_order_release); + + /* Stop the producer before the watchdog it can arm. */ + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_check_aml_temp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); } - rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); /* disable interrupts */ txgbe_disable_intr(hw); @@ -2926,6 +2936,7 @@ void txgbe_dev_check_aml_temp_event(void *param) void txgbe_dev_e56_check_bp_event(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 an_int1 = 0, value = 0, fsm = 0; u32 __rte_unused an_int = 0; @@ -2935,6 +2946,27 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3022,7 +3054,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->bp_event_interval = 2000 * 1000; out: - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0 && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); } @@ -3030,10 +3065,15 @@ static void txgbe_dev_detect_sfp(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; s32 err; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { @@ -3056,14 +3096,31 @@ txgbe_dev_detect_sfp(void *param) err = hw->phy.identify_sfp(hw); out: + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (!hw->adapter_stopped && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index a617b70e3c..08f41e628d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -368,6 +368,8 @@ struct txgbe_adapter { uint8_t rss_reta_updated; RTE_ATOMIC(uint32_t) link_thread_running; + /* SFP detection and AN73 watchdog alarm state. */ + RTE_ATOMIC(uint32_t) sfp_an_alarm_enabled; rte_thread_t link_thread_tid; }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the SFP/AN73 alarm gate is set, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 83ef9d8bfc..222c82694e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1984,6 +1984,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3068,7 +3073,7 @@ txgbe_dev_detect_sfp(void *param) struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, rte_memory_order_acquire) == 0) @@ -3080,6 +3085,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3123,6 +3133,14 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang ` (3 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 222c82694e..db773a1b9a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -483,6 +483,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u16 pballoc = 0; @@ -492,6 +493,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -540,6 +550,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -642,7 +660,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -650,6 +667,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The Amber-Lite E56 PHY has per-MAC FFE defaults that differ from the Sapphire defaults. In particular, the second pre-cursor tap defaults to zero, but callers need a devarg to override it when ffe_set is enabled. Add ffe_pre2 for the E56 second pre-cursor tap, and bp_capa for the 40G backplane advertisement selection. The latter supports the existing default of both KR4 and CR4, or either capability alone. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 18 +++++++++++++++--- doc/guides/rel_notes/release_26_11.rst | 8 ++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..61766cc4ac 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -132,17 +132,23 @@ Please note that following ``devargs`` are only set for backplane NICs. If disabled, the FFE parameters will not take effect. Otherwise, set 1 for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. -- ``ffe_main`` (default **27**) +- ``ffe_main`` (default **42** on the 25G Amber-Lite, **43** on the 40G + Amber-Lite, **27** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_pre`` (default **8**) +- ``ffe_pre`` (default **3** on Amber-Lite, **8** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_post`` (default **44**) +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **17** on Amber-Lite, **44** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. @@ -177,6 +183,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index dec96ccbc7..53da0dc66c 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -134,6 +134,14 @@ New Features * Changed the set of per-queue xstats counters. +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index db773a1b9a..cd54b696b4 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -492,13 +492,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -523,6 +530,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -535,6 +544,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -548,7 +559,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6481,12 +6494,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 +++++- 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 61766cc4ac..6aa6d4597f 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -189,6 +189,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 53da0dc66c..40ec9f457f 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -141,6 +141,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index cd54b696b4..999a8e9316 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -493,6 +493,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -546,6 +547,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -556,6 +559,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6501,7 +6505,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 14/15] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 2026-09-29 13:04 ` [PATCH v6 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt (1 ms step, 50-count round, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Avoid register reads that are only used by disabled BP debug logs, and drop a leftover debug line in the watchdog. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 173 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 24 +++- 7 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 760101a05e..8597e42dfd 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* 50ms timeout */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,31 +2395,87 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) + return; + + /* 21. read txffe to check kr training status */ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2436,6 +2505,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2532,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2584,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2630,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index da069e94f6..83fee14d12 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -31,10 +31,14 @@ extern int txgbe_logtype_bp; #define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp #define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) + do { \ + if (rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) \ + RTE_LOG(DEBUG, TXGBE_BP, \ + "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ + usec_stamp() / 1000000, \ + usec_stamp() % 1000000, \ + __func__, __LINE__, ## __VA_ARGS__); \ + } while (0) #define ASSERT(x) do { \ if (!(x)) \ diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 999a8e9316..973c70c282 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2984,6 +2984,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3009,7 +3010,7 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!txgbe_xpcs_an_enabled(hw)) return; if (!hw->devarg.auto_neg) @@ -3029,6 +3030,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3046,7 +3048,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3767,8 +3783,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v6 15/15] net/txgbe: align link capabilities and DAC classification [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-29 13:04 ` [PATCH v6 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-29 13:04 ` Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-29 13:04 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the four-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN. The XPCS AN gate queries the current link capabilities, so a subsequently hot-plugged AN-capable DAC is re-evaluated and can enable AN73 again. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 64 ++++++++++++++++++++++------ drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 19 ++++++++- drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 77 insertions(+), 22 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..f3d7c9f04a 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,11 +103,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { - hw->devarg.auto_neg = false; *autoneg = false; } else { *autoneg = true; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..f0456341a7 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,67 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static bool txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static bool txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + DEBUGOUT("port[%d] hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..11d38db4ba 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); @@ -2421,10 +2428,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw) int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) { + u32 speed; + bool autoneg; + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) return false; - return hw->devarg.auto_neg ? true : false; + if (!hw->devarg.auto_neg) + return false; + + /* Re-evaluate AN support for the currently detected module. */ + if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0) + return false; + + return autoneg; } /** diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 00/15] Wangxun fixes and new features [not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com> ` (22 preceding siblings ...) [not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com> @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 16:18 ` Stephen Hemminger [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> 24 siblings, 1 reply; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). --- v7: - P14: fix a TRAINING log-string typo. move the variable declarations in txgbe_e56_get_txffe(). clarify the comment of page-exchange timeout budget. --- v6: - fix the apply failure. --- v5: - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP tunnel, so the tunnel type cannot be resolved from the destination port. - P02: advertise 10G, 25G, and 40G from the requested speed mask instead of the device ID, so the 25G and 40G parts advertise 10G by default as well. - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; the AML40 default 10G|40G advertisement change is now in P02. - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port flag that dev_stop clears before the first cancel. cancel SFP detection before the watchdog. - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite FFE defaults. - P14: bound the AN page exchange, propagate its timeout to the watchdog h andler, and avoid register reads used only by disabled BP debug logs. - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; derive the effective AN73 state from the current module capabilities instead. Classify 40G active cables through the optical path, unify DAC checks on txgbe_is_dac_cable(). Not handled in this revision: - P12: bp_capa is not range-checked. Devarg validation will be added in a separate change so all txgbe devargs can be handled consistently. - P14: the AN page exchange still busy-waits on the alarm thread and can delay handling for other ports. A later change will decouple negotiation from the alarm callback and run per-port negotiations in parallel. --- Zaiyu Wang (15): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 FFE tap and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification doc/guides/nics/txgbe.rst | 25 +++- doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 92 ++++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 25 +++- drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 178 ++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_rxtx.c | 1 - 17 files changed, 502 insertions(+), 128 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v7 00/15] Wangxun fixes and new features 2026-09-30 10:17 ` [PATCH v7 00/15] Wangxun fixes and new features Zaiyu Wang @ 2026-09-30 16:18 ` Stephen Hemminger 0 siblings, 0 replies; 116+ messages in thread From: Stephen Hemminger @ 2026-09-30 16:18 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Wed, 30 Sep 2026 18:17:47 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs > (CR/KR training, hot-plug, 10G link state). > > --- > v7: > - P14: fix a TRAINING log-string typo. > move the variable declarations in txgbe_e56_get_txffe(). > clarify the comment of page-exchange timeout budget. > --- > v6: > - fix the apply failure. > --- > v5: > - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP > tunnel, so the tunnel type cannot be resolved from the destination port. > - P02: advertise 10G, 25G, and 40G from the requested speed mask instead > of the device ID, so the 25G and 40G parts advertise 10G by > default as well. > - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; > the AML40 default 10G|40G advertisement change is now in P02. > - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port > flag that dev_stop clears before the first cancel. > cancel SFP detection before the watchdog. > - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. > - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; > drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite > FFE defaults. > - P14: bound the AN page exchange, propagate its timeout to the watchdog h > andler, and avoid register reads used only by disabled BP debug logs. > - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; > derive the effective AN73 state from the current module capabilities > instead. Classify 40G active cables through the optical path, unify > DAC checks on txgbe_is_dac_cable(). > > Not handled in this revision: > > - P12: bp_capa is not range-checked. Devarg validation will be added in a > separate change so all txgbe devargs can be handled consistently. > - P14: the AN page exchange still busy-waits on the alarm thread and can > delay handling for other ports. A later change will decouple negotiation > from the alarm callback and run per-port negotiations in parallel. > --- > > Zaiyu Wang (15): > net/txgbe: fix failure to configure 10G on dual-speed DAC > net/txgbe: use the requested speed in E56 AN setup > net/txgbe: fix e56 PHY configuration error > net/txgbe: fix incorrect link state in 10G forced mode > net/txgbe: do not force reconfig on link retry > net/txgbe: set i2c sda hold time > net/txgbe: fix link speed display info for 10G mode > net/txgbe: remove stale outer UDP checksum offload flag > net/txgbe: fix SFP hot-plug when auto-negotiation is on > net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation > net/txgbe: fix 40G FFE tuning applied to first lane only > net/txgbe: add pre2 FFE tap and backplane capability devargs > net/txgbe: add devarg to turn off Tx laser for 40G NIC > net/txgbe: fix CR/KR link training and recovery > net/txgbe: align link capabilities and DAC classification > > doc/guides/nics/txgbe.rst | 25 +++- > doc/guides/rel_notes/release_26_11.rst | 11 ++ > drivers/net/txgbe/base/txgbe_aml.c | 4 +- > drivers/net/txgbe/base/txgbe_aml40.c | 92 ++++++++++-- > drivers/net/txgbe/base/txgbe_e56.c | 14 +- > drivers/net/txgbe/base/txgbe_e56.h | 6 + > drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++++---------- > drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- > drivers/net/txgbe/base/txgbe_hw.c | 33 +++++ > drivers/net/txgbe/base/txgbe_osdep.h | 12 +- > drivers/net/txgbe/base/txgbe_phy.c | 25 +++- > drivers/net/txgbe/base/txgbe_phy.h | 7 + > drivers/net/txgbe/base/txgbe_regs.h | 3 + > drivers/net/txgbe/base/txgbe_type.h | 17 ++- > drivers/net/txgbe/txgbe_ethdev.c | 178 ++++++++++++++++++++-- > drivers/net/txgbe/txgbe_ethdev.h | 2 + > drivers/net/txgbe/txgbe_rxtx.c | 1 - > 17 files changed, 502 insertions(+), 128 deletions(-) > There are several more things to address: Review: [PATCH v7 00/15] net/txgbe: Amber-Lite link and offload fixes The series applies to main (04d091f) except for the release notes hunks in 12/15 and 13/15. Every commit builds with -Dwerror=true (gcc 13.3, x86_64). All Fixes: tags resolve; the Amber-Lite commits are in 25.11 and 26.07, so Cc: stable is appropriate. Resolved since earlier rounds: - 09/15: AN73 watchdog can no longer be re-armed after dev_stop - 12/15: no longer tagged as a fix; the new FFE defaults are documented - 02/15: states the 10GBASE-KR advertisement change - 15/15: no longer clears devarg.auto_neg - 14/15: txgbe_e56_exchange_page() is bounded at 200 ms, and BP_LOG arguments are only evaluated when the log is enabled - 13/15: the commit message explains why the SFF-8636 Tx enable write is not gated on laser_off. That holds: the byte survives across runs while the module stays powered. The generic UDP tunnel patch is gone. Patch 15/15: net/txgbe: align link capabilities and DAC classification Error: 10G active limiting DAC on the 25G NIC fails to start txgbe_is_dac_cable() includes txgbe_sfp_type_da_act_lmt_core0/1. get_link_capabilities_aml() now takes the DAC branch for such a cable and reports *speed = hw->phy.fiber_suppport_speed. txgbe_identify_sfp_module() only assigns that field in the passive DA branch (and the QSFP path only for CR4); the DA_ACTIVE branch never does. On a fresh port it is 0. setup_phy_link_aml() masks the requested speed to nothing and returns TXGBE_ERR_LINK_SETUP, so dev_start fails. If a 25G passive DAC was in the cage earlier, the field is 25G|10G instead and AN73 is enabled on an active limiting cable. Before this patch, this cable took the fiber branch (10G|25G, no autoneg). Set fiber_suppport_speed to 10G in the DA_ACTIVE limiting branch. The passive branch has a related problem: it uses |= for the 10G-only case, which keeps the 25G bit from a previously inserted 25G DAC. The hot-plug support in 09/15 makes that reachable. Assign the value instead of OR-ing it. Info: txgbe_is_10g_fiber_sfp() cannot match on aml40. The srlr types are only set by txgbe_identify_sfp_module(), and aml40 identifies through txgbe_identify_qsfp_module(). Drop the branch. Patch 05/15: net/txgbe: do not force reconfig on link retry Warning: passing false also turns off need_restart autoneg_wait_to_complete is passed through to txgbe_e56_set_phy_link_mode() as need_restart. That function returns early when curbp_link_mode == 10. set_phy_link_mode() itself calls txgbe_set_phy_link_mode(hw, 10), so curbp_link_mode stays at 10 until training selects 25 or 40. As a result, a retry while the link is down and AN73 has not trained is now a no-op. The xpcs branch never sets need_reset, so the retry is not re-armed either, and recovery is left to the check_bp_event watchdog alone. Either say so in the commit message, or keep need_restart true when the link is down and rely on the link_up && an_done check for the case being fixed. Patch 10/15: net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Warning: the poll repeats identify for modules it cannot classify The poll skips identify when sfp_type != not_present. On aml40, txgbe_identify_qsfp_module() leaves sfp_type at not_present in two cases: - the identifier is not QSFP/QSFP+; it returns TXGBE_ERR_SFP_NOT_SUPPORTED - byte 131 has none of the CR4/SR4/LR4/active bits (extended compliance only, e.g. ER4); it returns 0 Both cases now repeat every 2 seconds on the EAL interrupt thread. Each repeat costs a 200 ms msec_delay() busy-wait plus I2C traffic. In the first case, each poll also logs two ERR lines. In the second case, each poll runs setup_sfp() and txgbe_dev_setup_link_alarm_handler(), which calls setup_link(hw, speed, true). On a down link that reaches txgbe_set_link_to_amlite(), with up to 2 s of msleep(). Without the poll, these paths ran only on a GPIO event. Record the last sampled module-present level in the adapter and run identify only on an absent-to-present transition. Alternatively, set sfp_type to txgbe_sfp_type_unknown when a module cannot be classified. Info: on optical modules, a module swapped between two polls keeps the old sfp_type. check_bp_event only samples the present pin while AN73 is enabled. Patch 13/15: net/txgbe: add devarg to turn off Tx laser for 40G NIC Warning: set_link_up does not undo the DAC disable With laser_off=1, txgbe_disable_tx_laser_multispeed_fiber() clears RX_EN, the Tx enable bits and PMD enable in PMD_CFG0 for DAC, unknown and absent modules. The enable path, txgbe_enable_tx_laser_multispeed_fiber(), has no counterpart; it only restores the SFF-8636 byte for optical modules. dev_start recovers because setup_link reprograms the PHY. rte_eth_dev_set_link_down() followed by rte_eth_dev_set_link_up() does not: set_link_up only calls enable_tx_laser() and link_update. The link thread is only started for txgbe_media_type_fiber, and aml40 is fiber_qsfp. With the Rx lanes off, check_bp_event sees no AN pages either, so a DAC link stays down. Either restore PMD_CFG0 in the enable path, or reconfigure the link in set_link_up. The documentation also says the laser is turned off "on port stop"; it applies to set_link_down as well. Patch 14/15: net/txgbe: fix CR/KR link training and recovery Warning: there is a stray "1" line after Signed-off-by, above the "---". git am keeps it as the last paragraph of the commit log, so git no longer finds any trailers in this commit. Drop it. Info: the commit message says the poll waits for 0x78010 == 0x9, but the code tests (rdata & 0x9) == 0x9, which also matches 0xb, 0xd and 0xf. If 0x78010[3:0] is an encoded FSM state, compare the field instead of masking it. Info: check_bp_event still busy-waits on the EAL interrupt thread: up to 200 ms in the page exchange, plus 400 ms in the CL72 poll, plus the RXS sequences (same as v4). Patch 11/15: net/txgbe: fix 40G FFE tuning applied to first lane only Info: S40G_TX_FFE_4LANE() masks the value to 8 bits. On aml40, any ffe_* value above 255 is silently truncated, while the parameter string still says uint16. Reject such values in txgbe_parse_devargs(). Patch 12/15: net/txgbe: add pre2 FFE tap and backplane capability devargs Info: bp_capa is still not range checked. On the 40G backplane, a value above 2 advertises no 40G ability at all (same as v4). Info: the release notes hunk no longer applies to main. Put "Updated Wangxun txgbe driver" between Solarflare and ZTE. ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <20260930102042.2214-1-zaiyuwang@trustnetic.com>]
* [PATCH v7 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (13 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0734a1c63c..d4c635dc2f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1848,7 +1848,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 02/15] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> 2026-09-30 10:17 ` [PATCH v7 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (12 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, as the base layer of the out-of-tree driver does: gate the 10G, 25G, and 40G advertisement on the requested speed and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. Both Amber-Lite MACs support 10GBASE-KR in addition to their nominal speed: the capability masks already report 10G|25G for the 25G MAC and 10G|40G for the 40G MAC, while the AN base page advertised exactly one speed picked from the device id. With automatic speed selection asking for 10G|40G on the 40G MAC as it already did 10G|25G on the 25G MAC, the base page advertises 10GBASE-KR together with 25GBASE-KR/CR on the 25G MAC and together with 40GBASE-KR4/CR4 on the 40G MAC. Explicit speed requests advertise only the requested modes. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), as the base layer does, and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 25 +++++++++++++++++++++---- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..760101a05e 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index d4c635dc2f..2f59b0794f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1864,7 +1864,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); @@ -1888,6 +1889,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -2951,7 +2966,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -2966,7 +2981,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -2975,7 +2991,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 03/15] net/txgbe: fix e56 PHY configuration error [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> 2026-09-30 10:17 ` [PATCH v7 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (11 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 04/15] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (10 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 05/15] net/txgbe: do not force reconfig on link retry [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang ` (9 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = true. On the AN73/xpcs path, setup_link skips reconfiguration when the link is already up and AN is done only if the flag is false. With true, a retry that arrives after the link is up still runs set_phy_link_mode() and resets the established AN73 link, which then drops and never recovers (e.g. after DAC hot-plug). Pass false from the retry path instead. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 2f59b0794f..a5ef0b3e54 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3237,7 +3237,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 06/15] net/txgbe: set i2c sda hold time [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (8 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 07/15] net/txgbe: fix link speed display info for 10G mode [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (7 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, so a 10G link is reported as 10G. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..d812adac69 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 08/15] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (6 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (5 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. The SFP detection alarm and the AN73 watchdog are gated on a per-port flag that txgbe_dev_start() sets before the alarms are armed and txgbe_dev_stop() clears before it cancels anything, so a handler already running on the alarm thread can neither re-arm itself nor arm the other one on a port that is being stopped. The flag goes low before the cancels because hw->adapter_stopped is only set at the end of txgbe_dev_stop(). The link thread can arm the AML link alarm while txgbe_dev_stop() waits for it, so cancel that alarm again after the thread has been joined. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 61 ++++++++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 ++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index a5ef0b3e54..83ef9d8bfc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1695,6 +1695,7 @@ txgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, static int txgbe_dev_start(struct rte_eth_dev *dev) { + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct txgbe_hw_stats *hw_stats = TXGBE_DEV_STATS(dev); struct txgbe_vf_info *vfinfo = *TXGBE_DEV_VFDATA(dev); @@ -1970,6 +1971,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_dev_rxq_interrupt_setup(dev); /* enable uio/vfio intr/eventfd mapping */ + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 1, + rte_memory_order_release); rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ @@ -2027,15 +2030,22 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 0, + rte_memory_order_release); + + /* Stop the producer before the watchdog it can arm. */ + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_check_aml_temp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); } - rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); /* disable interrupts */ txgbe_disable_intr(hw); @@ -2926,6 +2936,7 @@ void txgbe_dev_check_aml_temp_event(void *param) void txgbe_dev_e56_check_bp_event(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 an_int1 = 0, value = 0, fsm = 0; u32 __rte_unused an_int = 0; @@ -2935,6 +2946,27 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3022,7 +3054,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->bp_event_interval = 2000 * 1000; out: - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0 && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); } @@ -3030,10 +3065,15 @@ static void txgbe_dev_detect_sfp(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; s32 err; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { @@ -3056,14 +3096,31 @@ txgbe_dev_detect_sfp(void *param) err = hw->phy.identify_sfp(hw); out: + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (!hw->adapter_stopped && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index a617b70e3c..08f41e628d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -368,6 +368,8 @@ struct txgbe_adapter { uint8_t rss_reta_updated; RTE_ATOMIC(uint32_t) link_thread_running; + /* SFP detection and AN73 watchdog alarm state. */ + RTE_ATOMIC(uint32_t) sfp_an_alarm_enabled; rte_thread_t link_thread_tid; }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (4 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Two problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. The poll skips the identify step while the level is unchanged, and only re-arms itself while the SFP/AN73 alarm gate is set, so that it cannot survive txgbe_dev_stop(). Second, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/txgbe_ethdev.c | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index d812adac69..2d3b32839c 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -177,6 +177,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 83ef9d8bfc..222c82694e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1984,6 +1984,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3068,7 +3073,7 @@ txgbe_dev_detect_sfp(void *param) struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, rte_memory_order_acquire) == 0) @@ -3080,6 +3085,11 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* The level is unchanged since the last poll, so the cached + * module type is still valid and identify can be skipped. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3123,6 +3133,14 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:17 ` [PATCH v7 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang ` (3 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f9b5cbe61a..4ed4737043 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 222c82694e..db773a1b9a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -483,6 +483,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u16 pballoc = 0; @@ -492,6 +493,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -540,6 +550,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -642,7 +660,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -650,6 +667,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-09-30 10:17 ` Zaiyu Wang 2026-09-30 10:18 ` [PATCH v7 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (2 subsequent siblings) 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:17 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The Amber-Lite E56 PHY has per-MAC FFE defaults that differ from the Sapphire defaults. In particular, the second pre-cursor tap defaults to zero, but callers need a devarg to override it when ffe_set is enabled. Add ffe_pre2 for the E56 second pre-cursor tap, and bp_capa for the 40G backplane advertisement selection. The latter supports the existing default of both KR4 and CR4, or either capability alone. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 18 +++++++++++++++--- doc/guides/rel_notes/release_26_11.rst | 8 ++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..61766cc4ac 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -132,17 +132,23 @@ Please note that following ``devargs`` are only set for backplane NICs. If disabled, the FFE parameters will not take effect. Otherwise, set 1 for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. -- ``ffe_main`` (default **27**) +- ``ffe_main`` (default **42** on the 25G Amber-Lite, **43** on the 40G + Amber-Lite, **27** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_pre`` (default **8**) +- ``ffe_pre`` (default **3** on Amber-Lite, **8** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_post`` (default **44**) +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **17** on Amber-Lite, **44** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. @@ -177,6 +183,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index dec96ccbc7..53da0dc66c 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -134,6 +134,14 @@ New Features * Changed the set of per-queue xstats counters. +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 4ed4737043..f56cd70c6f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index db773a1b9a..cd54b696b4 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -492,13 +492,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -523,6 +530,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -535,6 +544,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -548,7 +559,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6481,12 +6494,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-09-30 10:17 ` [PATCH v7 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang @ 2026-09-30 10:18 ` Zaiyu Wang 2026-09-30 10:18 ` [PATCH v7 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang 2026-09-30 10:18 ` [PATCH v7 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss (e.g. for link-state tracking at the peer). Add a laser_off devarg: when enabled, bring the Tx laser down on port stop -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 3 +++ drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 7 +++++- 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 61766cc4ac..6aa6d4597f 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -189,6 +189,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 53da0dc66c..40ec9f457f 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -141,6 +141,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index f56cd70c6f..39a70746a7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index cd54b696b4..999a8e9316 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -493,6 +493,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -546,6 +547,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -556,6 +559,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -6501,7 +6505,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 14/15] net/txgbe: fix CR/KR link training and recovery [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-09-30 10:18 ` [PATCH v7 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-09-30 10:18 ` Zaiyu Wang 2026-09-30 10:18 ` [PATCH v7 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010, value 0x9) for CL72 completion with a 1 ms step and a 400 ms budget, replacing the ephy 0x163c mask-0xe poll that tested the wrong condition; the per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt (1 ms step, 50-count round, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds; the inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Avoid register reads that are only used by disabled BP debug logs, and drop a leftover debug line in the watchdog. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> 1 --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 173 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 24 +++- 7 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 760101a05e..7656da5cd0 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* Allow up to 50 ms per page-exchange round, with a 200 ms total budget. */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,31 +2395,87 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) + return; + + /* 21. read txffe to check kr training status */ + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2436,6 +2505,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2532,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2584,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2630,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index da069e94f6..83fee14d12 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -31,10 +31,14 @@ extern int txgbe_logtype_bp; #define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp #define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) + do { \ + if (rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) \ + RTE_LOG(DEBUG, TXGBE_BP, \ + "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ + usec_stamp() / 1000000, \ + usec_stamp() % 1000000, \ + __func__, __LINE__, ## __VA_ARGS__); \ + } while (0) #define ASSERT(x) do { \ if (!(x)) \ diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..10df23afae 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1947,6 +1947,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 999a8e9316..973c70c282 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2984,6 +2984,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3009,7 +3010,7 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!txgbe_xpcs_an_enabled(hw)) return; if (!hw->devarg.auto_neg) @@ -3029,6 +3030,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3046,7 +3048,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3767,8 +3783,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v7 15/15] net/txgbe: align link capabilities and DAC classification [not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-09-30 10:18 ` [PATCH v7 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-09-30 10:18 ` Zaiyu Wang 14 siblings, 0 replies; 116+ messages in thread From: Zaiyu Wang @ 2026-09-30 10:18 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu An active DAC can be misidentified as a 40G optical module, in which case the driver reports 40G and enables autoneg for a module that does not support it; DACs and optical modules are also treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Port the four-branch capability layout to AML40: backplane, DAC (txgbe_is_dac_cable() plus the 10G-only AN-off case), 40G QSFP and 10G SFP. Modules previously misreported as 40G through the fallback now report the correct speed and autoneg. - Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN. The XPCS AN gate queries the current link capabilities, so a subsequently hot-plugged AN-capable DAC is re-evaluated and can enable AN73 again. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 4 +- drivers/net/txgbe/base/txgbe_aml40.c | 64 ++++++++++++++++++++++------ drivers/net/txgbe/base/txgbe_e56.c | 9 ++-- drivers/net/txgbe/base/txgbe_phy.c | 19 ++++++++- drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + 6 files changed, 77 insertions(+), 22 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..f3d7c9f04a 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,11 +103,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { - hw->devarg.auto_neg = false; *autoneg = false; } else { *autoneg = true; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 2d3b32839c..f0456341a7 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,67 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static bool txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + +static bool txgbe_is_10g_fiber_sfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_srlr_core0 || + hw->phy.sfp_type == txgbe_sfp_type_srlr_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + DEBUGOUT("port[%d] hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; + } else if (txgbe_is_10g_fiber_sfp(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 10df23afae..11d38db4ba 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1156,6 +1156,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); @@ -2421,10 +2428,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw) int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) { + u32 speed; + bool autoneg; + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) return false; - return hw->devarg.auto_neg ? true : false; + if (!hw->devarg.auto_neg) + return false; + + /* Re-evaluate AN support for the currently detected module. */ + if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0) + return false; + + return autoneg; } /** diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 39a70746a7..91771b9cbd 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 116+ messages in thread
end of thread, other threads:[~2026-09-30 16:18 UTC | newest]
Thread overview: 116+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260827114309.10530-1-zaiyuwang@trustnetic.com>
2026-08-27 11:41 ` [PATCH 01/13] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-08-27 11:41 ` [PATCH 02/13] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-08-27 11:41 ` [PATCH 03/13] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-08-27 11:41 ` [PATCH 04/13] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-08-27 11:41 ` [PATCH 05/13] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-08-27 11:41 ` [PATCH 06/13] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-08-27 11:41 ` [PATCH 07/13] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang
2026-08-27 11:42 ` [PATCH 08/13] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-08-27 11:42 ` [PATCH 09/13] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-08-27 11:42 ` [PATCH 10/13] net/txgbe: add backplane FFE and capability devargs Zaiyu Wang
2026-08-27 11:42 ` [PATCH 11/13] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-08-27 11:42 ` [PATCH 12/13] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-08-27 11:42 ` [PATCH 13/13] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 00/15] Wangxun fixes and new features Zaiyu Wang
[not found] ` <20260908124047.2284-1-zaiyuwang@trustnetic.com>
2026-09-08 12:38 ` [PATCH v2 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-08 12:38 ` [PATCH v2 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-08 12:39 ` [PATCH v2 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 00/15] Wangxun fixes and new features Zaiyu Wang
2026-09-08 14:20 ` Stephen Hemminger
[not found] ` <20260908132742.2661-1-zaiyuwang@trustnetic.com>
2026-09-08 13:25 ` [PATCH v3 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 02/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 03/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 04/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 05/15] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 06/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 07/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 08/15] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 12/15] net/txgbe: add pre2 and backplane capability devargs Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-08 13:25 ` [PATCH v3 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-08 13:26 ` [PATCH v3 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 00/16] Wangxun fixes and new features Zaiyu Wang
2026-09-22 13:35 ` Stephen Hemminger
2026-09-29 11:21 ` Zaiyu Wang
[not found] ` <20260922125414.3638-1-zaiyuwang@trustnetic.com>
2026-09-22 12:37 ` [PATCH v4 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 09/16] net/txgbe: add offload support for tunnel type UDP Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 10/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 11/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 12/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 13/16] net/txgbe: fix unset pre2 FFE tap and backplane capability Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 14/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 15/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-22 12:37 ` [PATCH v4 16/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 00/15] Wangxun fixes and new features Zaiyu Wang
[not found] ` <20260929112119.4516-1-zaiyuwang@trustnetic.com>
2026-09-29 11:18 ` [PATCH v5 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-29 11:18 ` [PATCH v5 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 00/15] Wangxun fixes and new features Zaiyu Wang
2026-09-29 16:05 ` Stephen Hemminger
2026-09-30 10:22 ` Zaiyu Wang
[not found] ` <20260929130611.4871-1-zaiyuwang@trustnetic.com>
2026-09-29 13:04 ` [PATCH v6 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-29 13:04 ` [PATCH v6 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 00/15] Wangxun fixes and new features Zaiyu Wang
2026-09-30 16:18 ` Stephen Hemminger
[not found] ` <20260930102042.2214-1-zaiyuwang@trustnetic.com>
2026-09-30 10:17 ` [PATCH v7 01/15] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 02/15] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 03/15] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 04/15] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 05/15] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 06/15] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 07/15] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 08/15] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 09/15] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 10/15] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 11/15] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-09-30 10:17 ` [PATCH v7 12/15] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang
2026-09-30 10:18 ` [PATCH v7 13/15] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-09-30 10:18 ` [PATCH v7 14/15] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-09-30 10:18 ` [PATCH v7 15/15] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox