A 10G active-limiting DAC on an Amber-Lite 25G NIC has no
fiber_suppport_speed value, so the capability path rejects it. A
10G-only passive DAC can also retain a stale 25G bit after hot-plug.
DACs and optical modules are additionally treated differently in the
FFE, CTLE and capability-report paths.

Rework the AML40/AML link capabilities and DAC classification:

- Use the detected DAC speed in the capability paths. Assign 10G for
  passive 10G-only and active-limiting DACs instead of preserving a
  speed value left by the previously installed module.
- Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN.
  The XPCS AN gate queries the current link capabilities, so a
  subsequently hot-plugged AN-capable DAC is re-evaluated and can
  enable AN73 again.
- Add the 40G-active transceiver identification (sfp_type enum and
  identify branch). Like the kernel driver, 40G active cables are
  handled through the optical path, as SFF-8636 byte 131 bit 0
  ("40G Active Cable") also covers active optical cables.
- Unify DAC classification on txgbe_is_dac_cable(), including the
  40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded
  the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt)
  is no longer treated as an optical module.
- Remove the AML40 10G SFP capability branch. AML40 identifies QSFP
  modules and cannot produce the SFP SR/LR types tested by that
  branch.

Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite")
Cc: [email protected]

Signed-off-by: Zaiyu Wang <[email protected]>
---
 drivers/net/txgbe/base/txgbe_aml.c   |  4 +--
 drivers/net/txgbe/base/txgbe_aml40.c | 52 +++++++++++++++++++++-------
 drivers/net/txgbe/base/txgbe_e56.c   |  9 ++---
 drivers/net/txgbe/base/txgbe_phy.c   | 23 ++++++++++--
 drivers/net/txgbe/base/txgbe_phy.h   |  1 +
 drivers/net/txgbe/base/txgbe_type.h  |  2 ++
 6 files changed, 68 insertions(+), 23 deletions(-)

diff --git a/drivers/net/txgbe/base/txgbe_aml.c 
b/drivers/net/txgbe/base/txgbe_aml.c
index 7a0839a7d1..ae5c7d7f0d 100644
--- a/drivers/net/txgbe/base/txgbe_aml.c
+++ b/drivers/net/txgbe/base/txgbe_aml.c
@@ -103,11 +103,9 @@ 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;
                        *autoneg = false;
                } else {
                        *autoneg = true;
diff --git a/drivers/net/txgbe/base/txgbe_aml40.c 
b/drivers/net/txgbe/base/txgbe_aml40.c
index cee2f2880a..4080302ce7 100644
--- a/drivers/net/txgbe/base/txgbe_aml40.c
+++ b/drivers/net/txgbe/base/txgbe_aml40.c
@@ -95,27 +95,55 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 
*speed,
        return 0;
 }
 
+static bool 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;
+}
+
 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 = hw->phy.fiber_suppport_speed;
-               *autoneg = hw->devarg.auto_neg;
-       } else if (txgbe_is_backplane(hw)) {
-               *speed = TXGBE_LINK_SPEED_40GB_FULL |
-                        TXGBE_LINK_SPEED_10GB_FULL;
+       DEBUGOUT("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)) {
+               if (hw->phy.fiber_suppport_speed ==
+                   TXGBE_LINK_SPEED_10GB_FULL) {
+                       *autoneg = false;
+               } else {
+                       *autoneg = hw->devarg.auto_neg;
+               }
+               *speed = hw->phy.fiber_suppport_speed;
+       } else if (txgbe_is_40g_fiber_qsfp(hw)) {
+               *speed = TXGBE_LINK_SPEED_40GB_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..f996113ab8 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;
@@ -92,8 +91,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;
 
-               if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 ||
-                   hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 ||
+               if (txgbe_is_dac_cable(hw) ||
                    txgbe_is_backplane(hw)) {
                        ffe_main = S40G_TX_FFE_CFG_MAIN;
                        pre1 = S40G_TX_FFE_CFG_PRE1;
@@ -2622,8 +2620,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 decfcbadd6..896fe7eecf 100644
--- a/drivers/net/txgbe/base/txgbe_phy.c
+++ b/drivers/net/txgbe/base/txgbe_phy.c
@@ -917,7 +917,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw)
                                TXGBE_LINK_SPEED_25GB_FULL |
                                TXGBE_LINK_SPEED_10GB_FULL;
                } else {
-                       hw->phy.fiber_suppport_speed |=
+                       hw->phy.fiber_suppport_speed =
                                TXGBE_LINK_SPEED_10GB_FULL;
                }
        } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 ||
@@ -938,6 +938,8 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw)
                        hw->phy.sfp_type = (hw->bus.lan_id == 0
                                ? txgbe_sfp_type_da_act_lmt_core0
                                : txgbe_sfp_type_da_act_lmt_core1);
+                       hw->phy.fiber_suppport_speed =
+                               TXGBE_LINK_SPEED_10GB_FULL;
                } else {
                        hw->phy.sfp_type = txgbe_sfp_type_unknown;
                }
@@ -1158,6 +1160,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;
+               }
        }
 
        if (err == 0 && hw->mac.type == txgbe_mac_aml40 &&
@@ -2430,10 +2439,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw)
 
 int txgbe_xpcs_an_enabled(struct txgbe_hw *hw)
 {
+       u32 speed;
+       bool autoneg;
+
        if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)))
                return false;
 
-       return hw->devarg.auto_neg ? true : false;
+       if (!hw->devarg.auto_neg)
+               return false;
+
+       /* Re-evaluate AN support for the currently detected module. */
+       if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0)
+               return false;
+
+       return autoneg;
 }
 
 /**
diff --git a/drivers/net/txgbe/base/txgbe_phy.h 
b/drivers/net/txgbe/base/txgbe_phy.h
index a06c0eb04e..552fedadab 100644
--- a/drivers/net/txgbe/base/txgbe_phy.h
+++ b/drivers/net/txgbe/base/txgbe_phy.h
@@ -316,6 +316,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 33e306ac70..a1ce78623b 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


Reply via email to