Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci/ixgbe Add recovery code for unsupported SFP+.



details:   https://anonhg.NetBSD.org/src/rev/de0f4d568a24
branches:  trunk
changeset: 967812:de0f4d568a24
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Mon Dec 23 09:36:17 2019 +0000

description:
Add recovery code for unsupported SFP+.

Before this commit:
   If an unsuppored SFP module is inserted before booting, the driver attach
   failed and there was no way to recover form it without rebooting or
   detaching/reattaching drvier (drvctl -d && drvctl -r pciN).
After this commit:
   We can automatically recover any time by replacing it with a supported
   module.

diffstat:

 sys/dev/pci/ixgbe/ixgbe.c       |  85 +++++++++++++++++++++++++---------------
 sys/dev/pci/ixgbe/ixgbe_82598.c |   7 +-
 sys/dev/pci/ixgbe/ixgbe_82599.c |  23 ++++++----
 sys/dev/pci/ixgbe/ixgbe_phy.c   |   6 ++-
 sys/dev/pci/ixgbe/ixgbe_type.h  |   3 +-
 sys/dev/pci/ixgbe/ixgbe_x550.c  |  22 ++++++----
 6 files changed, 89 insertions(+), 57 deletions(-)

diffs (truncated from 359 to 300 lines):

diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Mon Dec 23 09:19:40 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Mon Dec 23 09:36:17 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.218 2019/12/23 09:19:40 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.219 2019/12/23 09:36:17 msaitoh Exp $ */
 
 /******************************************************************************
 
@@ -776,6 +776,7 @@
        pcireg_t        id, subid;
        const ixgbe_vendor_info_t *ent;
        struct pci_attach_args *pa = aux;
+       bool unsupported_sfp = false;
        const char *str;
        char buf[256];
 
@@ -954,8 +955,8 @@
                error = IXGBE_SUCCESS;
        } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
                aprint_error_dev(dev, "Unsupported SFP+ module detected!\n");
-               error = EIO;
-               goto err_late;
+               unsupported_sfp = true;
+               error = IXGBE_SUCCESS;
        } else if (error) {
                aprint_error_dev(dev, "Hardware initialization failed\n");
                error = EIO;
@@ -1126,13 +1127,6 @@
                    "please contact your Intel or hardware representative "
                    "who provided you with this hardware.\n");
                break;
-       case IXGBE_ERR_SFP_NOT_SUPPORTED:
-               aprint_error_dev(dev, "Unsupported SFP+ Module\n");
-               error = EIO;
-               goto err_late;
-       case IXGBE_ERR_SFP_NOT_PRESENT:
-               aprint_error_dev(dev, "No SFP+ Module found\n");
-               /* falls thru */
        default:
                break;
        }
@@ -1165,16 +1159,22 @@
                            oui, model, rev);
        }
 
-       /* Enable the optics for 82599 SFP+ fiber */
-       ixgbe_enable_tx_laser(hw);
-
        /* Enable EEE power saving */
        if (adapter->feat_cap & IXGBE_FEATURE_EEE)
                hw->mac.ops.setup_eee(hw,
                    adapter->feat_en & IXGBE_FEATURE_EEE);
 
        /* Enable power to the phy. */
-       ixgbe_set_phy_power(hw, TRUE);
+       if (!unsupported_sfp) {
+               /* Enable the optics for 82599 SFP+ fiber */
+               ixgbe_enable_tx_laser(hw);
+
+               /*
+                * XXX Currently, ixgbe_set_phy_power() supports only copper
+                * PHY, so it's not required to test with !unsupported_sfp.
+                */
+               ixgbe_set_phy_power(hw, TRUE);
+       }
 
        /* Initialize statistics */
        ixgbe_update_stats_counters(adapter);
@@ -3901,6 +3901,7 @@
        u32             txdctl, mhadd;
        u32             rxdctl, rxctrl;
        u32             ctrl_ext;
+       bool            unsupported_sfp = false;
        int             i, j, err;
 
        /* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
@@ -3908,6 +3909,7 @@
        KASSERT(mutex_owned(&adapter->core_mtx));
        INIT_DEBUGOUT("ixgbe_init_locked: begin");
 
+       hw->need_unsupported_sfp_recovery = false;
        hw->adapter_stopped = FALSE;
        ixgbe_stop_adapter(hw);
        callout_stop(&adapter->timer);
@@ -4081,12 +4083,14 @@
         */
        if (hw->phy.type == ixgbe_phy_none) {
                err = hw->phy.ops.identify(hw);
-               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-                       device_printf(dev,
-                           "Unsupported SFP+ module type was detected.\n");
-                       return;
-               }
-       }
+               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+                       unsupported_sfp = true;
+       } else if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+               unsupported_sfp = true;
+
+       if (unsupported_sfp)
+               device_printf(dev,
+                   "Unsupported SFP+ module type was detected.\n");
 
        /* Set moderation on the Link interrupt */
        ixgbe_eitr_write(adapter, adapter->vector, IXGBE_LINK_ITR);
@@ -4097,10 +4101,12 @@
                    adapter->feat_en & IXGBE_FEATURE_EEE);
 
        /* Enable power to the phy. */
-       ixgbe_set_phy_power(hw, TRUE);
-
-       /* Config/Enable Link */
-       ixgbe_config_link(adapter);
+       if (!unsupported_sfp) {
+               ixgbe_set_phy_power(hw, TRUE);
+
+               /* Config/Enable Link */
+               ixgbe_config_link(adapter);
+       }
 
        /* Hardware Packet Buffer & Flow Control setup */
        ixgbe_config_delay_values(adapter);
@@ -4636,15 +4642,28 @@
                goto out;
        }
 
-       if (hw->mac.type == ixgbe_mac_82598EB)
-               err = hw->phy.ops.reset(hw);
-       else
-               err = hw->mac.ops.setup_sfp(hw);
-
-       if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-               device_printf(dev,
-                   "Setup failure - unsupported SFP+ module type.\n");
-               goto out;
+       if (hw->need_unsupported_sfp_recovery) {
+               device_printf(dev, "Recovering from unsupported SFP\n");
+               /*
+                *  We could recover the status by calling setup_sfp(),
+                * setup_link() and some others. It's complex and might not
+                * work correctly on some unknown cases. To avoid such type of
+                * problem, call ixgbe_init_locked(). It's simple and safe
+                * approach.
+                */
+               ixgbe_init_locked(adapter);
+       } else {
+               if (hw->mac.type == ixgbe_mac_82598EB)
+                       err = hw->phy.ops.reset(hw);
+               else {
+                       err = hw->mac.ops.setup_sfp(hw);
+                       hw->phy.sfp_setup_needed = FALSE;
+               }
+               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+                       device_printf(dev,
+                           "Setup failure - unsupported SFP+ module type.\n");
+                       goto out;
+               }
        }
        softint_schedule(adapter->msf_si);
 out:
diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe_82598.c
--- a/sys/dev/pci/ixgbe/ixgbe_82598.c   Mon Dec 23 09:19:40 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_82598.c   Mon Dec 23 09:36:17 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82598.c,v 1.12 2018/04/04 08:59:22 msaitoh Exp $ */
+/* $NetBSD: ixgbe_82598.c,v 1.13 2019/12/23 09:36:17 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -866,9 +866,8 @@
 
                /* Init PHY and function pointers, perform SFP setup */
                phy_status = hw->phy.ops.init(hw);
-               if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-                       goto reset_hw_out;
-               if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+               if ((phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED) ||
+                   (phy_status == IXGBE_ERR_SFP_NOT_PRESENT))
                        goto mac_reset_top;
 
                hw->phy.ops.reset(hw);
diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe_82599.c
--- a/sys/dev/pci/ixgbe/ixgbe_82599.c   Mon Dec 23 09:19:40 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_82599.c   Mon Dec 23 09:36:17 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82599.c,v 1.21 2018/12/06 13:25:02 msaitoh Exp $ */
+/* $NetBSD: ixgbe_82599.c,v 1.22 2019/12/23 09:36:17 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -1041,6 +1041,7 @@
 {
        ixgbe_link_speed link_speed;
        s32 status;
+       s32 phy_status = IXGBE_SUCCESS;
        u32 ctrl = 0;
        u32 i, autoc, autoc2;
        u32 curr_lms;
@@ -1059,28 +1060,29 @@
        /* PHY ops must be identified and initialized prior to reset */
 
        /* Identify PHY and related function pointers */
-       status = hw->phy.ops.init(hw);
+       phy_status = hw->phy.ops.init(hw);
 
-       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-               goto reset_hw_out;
+       if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               goto mac_reset_top;
 
        /* Setup SFP module if there is one present. */
        if (hw->phy.sfp_setup_needed) {
-               status = hw->mac.ops.setup_sfp(hw);
+               phy_status = hw->mac.ops.setup_sfp(hw);
                hw->phy.sfp_setup_needed = FALSE;
        }
 
-       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-               goto reset_hw_out;
+       if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               goto mac_reset_top;
 
        /* Reset PHY */
        if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
                hw->phy.ops.reset(hw);
 
+mac_reset_top:
        /* remember AUTOC from before we reset */
        curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
 
-mac_reset_top:
+mac_reset_retry:
        /*
         * Issue global reset to the MAC.  Needs to be SW reset if link is up.
         * If link reset is used when link is up, it might reset the PHY when
@@ -1120,7 +1122,7 @@
         */
        if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
                hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
-               goto mac_reset_top;
+               goto mac_reset_retry;
        }
 
        /*
@@ -1208,6 +1210,9 @@
                                   &hw->mac.wwpn_prefix);
 
 reset_hw_out:
+       if (phy_status != IXGBE_SUCCESS)
+               status = phy_status;
+
        return status;
 }
 
diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe_phy.c
--- a/sys/dev/pci/ixgbe/ixgbe_phy.c     Mon Dec 23 09:19:40 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_phy.c     Mon Dec 23 09:36:17 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_phy.c,v 1.19 2019/12/16 02:50:54 msaitoh Exp $ */
+/* $NetBSD: ixgbe_phy.c,v 1.20 2019/12/23 09:36:18 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -1585,6 +1585,8 @@
        }
 
 out:
+       if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+               hw->need_unsupported_sfp_recovery = true;
        return status;
 
 err_read_i2c_eeprom:
@@ -1838,6 +1840,8 @@
        }
 
 out:
+       if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+               hw->need_unsupported_sfp_recovery = true;
        return status;
 
 err_read_i2c_eeprom:
diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe_type.h
--- a/sys/dev/pci/ixgbe/ixgbe_type.h    Mon Dec 23 09:19:40 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_type.h    Mon Dec 23 09:36:17 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.43 2019/09/20 09:28:37 msaitoh Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.44 2019/12/23 09:36:18 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -4263,6 +4263,7 @@
        bool allow_unsupported_sfp;
        bool wol_enabled;
        bool need_crosstalk_fix;
+       bool need_unsupported_sfp_recovery;
 };
 
 #define ixgbe_call_func(hw, func, params, error) \
diff -r 636f1a0dcf0f -r de0f4d568a24 sys/dev/pci/ixgbe/ixgbe_x550.c



Home | Main Index | Thread Index | Old Index