Hot-plugging a DAC cable while an Amber-Lite 40G port is running
does not bring the link up. Three 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. Identification is
attempted only when the cached module state is not present, and the
poll re-arms itself only while the SFP/AN73 alarm gate is set, so that
it cannot survive txgbe_dev_stop().

Second, on AML40, an unsupported QSFP identifier, or a QSFP module
with no supported capability bit, previously left the cached state as
not present. The poll then repeated the delay and I2C reads
indefinitely, and the latter case also repeated module and link setup.
Record these modules as unknown and return not supported so polling
resumes only after an observed removal.

Third, 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/base/txgbe_phy.c   |  9 +++++++++
 drivers/net/txgbe/txgbe_ethdev.c     | 18 +++++++++++++++++-
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/net/txgbe/base/txgbe_aml40.c 
b/drivers/net/txgbe/base/txgbe_aml40.c
index b52702b197..cee2f2880a 100644
--- a/drivers/net/txgbe/base/txgbe_aml40.c
+++ b/drivers/net/txgbe/base/txgbe_aml40.c
@@ -180,6 +180,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, need_restart);
                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/base/txgbe_phy.c 
b/drivers/net/txgbe/base/txgbe_phy.c
index 8b653f0aeb..a50fa986b9 100644
--- a/drivers/net/txgbe/base/txgbe_phy.c
+++ b/drivers/net/txgbe/base/txgbe_phy.c
@@ -1125,6 +1125,8 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw)
                PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, 
identifier = 0x%x",
                             hw->bus.lan_id, identifier);
                hw->phy.type = txgbe_phy_sfp_unsupported;
+               if (hw->mac.type == txgbe_mac_aml40)
+                       hw->phy.sfp_type = txgbe_sfp_type_unknown;
                err = TXGBE_ERR_SFP_NOT_SUPPORTED;
        } else {
                err = hw->phy.read_i2c_sff8636(hw, 0,
@@ -1158,6 +1160,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw)
                }
        }
 
+       if (err == 0 && hw->mac.type == txgbe_mac_aml40 &&
+           hw->phy.sfp_type == txgbe_sfp_type_not_present) {
+               hw->phy.type = txgbe_phy_sfp_unsupported;
+               hw->phy.sfp_type = txgbe_sfp_type_unknown;
+               err = TXGBE_ERR_SFP_NOT_SUPPORTED;
+       }
+
        hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY);
        return err;
 
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 83ef9d8bfc..8e2adb245e 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,9 @@ txgbe_dev_detect_sfp(void *param)
                        err = TXGBE_ERR_SFP_NOT_PRESENT;
                        goto out;
                }
+               /* Re-identification is only attempted from the not-present 
state. */
+               if (hw->phy.sfp_type != txgbe_sfp_type_not_present)
+                       goto rearm;
        }
 
        if (hw->mac.type == txgbe_mac_aml) {
@@ -3123,6 +3131,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

Reply via email to