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: [email protected]

Signed-off-by: Zaiyu Wang <[email protected]>
---
 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

Reply via email to