[PATCH 13/13] net/txgbe: align link capabilities and DAC classification
From: Zaiyu Wang <hidden>
Date: 2026-08-27 11:44:56
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted>
---
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