[PATCH 08/13] net/txgbe: fix SFP hot-plug when auto-negotiation is on
From: Zaiyu Wang <hidden>
Date: 2026-08-27 11:44:25
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted>
---
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