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

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


Reply via email to