Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Add some code for suspend/resume:



details:   https://anonhg.NetBSD.org/src/rev/13dfbd2e644b
branches:  trunk
changeset: 446604:13dfbd2e644b
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Wed Dec 12 08:49:33 2018 +0000

description:
Add some code for suspend/resume:
- Rename wm_smbustopci() to wm_init_phy_workarounds_pchlan(). It will also
  called when resume.
- Call wm_phy_resetisblocked() after PHY reset in
  wm_init_phy_workarounds_pchlan() to wait for the PHY to quiesce to an
  accessible state.
- Add new wm_resume_workarounds_pchlan() function and use it in wm_resume().
  This workaround is only for PCH2 and newer.
- Don't call wm_disable_aspm() neither in wm_attach() nor in wm_resume()
  but in wm_reset().
- Do some initialization in wm_resume() when IFF_UP is NOT set.
- Don't continue when it failed to acquire semaphore in wm_ulp_disable().
- Add comment.

diffstat:

 sys/dev/mii/inbmphyreg.h |   18 ++++-
 sys/dev/pci/if_wm.c      |  170 ++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 164 insertions(+), 24 deletions(-)

diffs (truncated from 366 to 300 lines):

diff -r 0ce2f7eab4dd -r 13dfbd2e644b sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h  Wed Dec 12 08:28:44 2018 +0000
+++ b/sys/dev/mii/inbmphyreg.h  Wed Dec 12 08:49:33 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: inbmphyreg.h,v 1.12 2018/11/22 15:09:45 msaitoh Exp $  */
+/*     $NetBSD: inbmphyreg.h,v 1.13 2018/12/12 08:49:33 msaitoh Exp $  */
 /*******************************************************************************
 Copyright (c) 2001-2005, Intel Corporation 
 All rights reserved.
@@ -126,6 +126,20 @@
 #define        IGP3_KMRN_DIAG          BME1000_REG(770, 19)
 #define        IGP3_KMRN_DIAG_PCS_LOCK_LOSS    (1 << 1)
 
+#define        I217_LPI_GPIO_CTRL      BME1000_REG(772, 18)
+#define        I217_LPI_GPIO_CTRL_AUTO_EN_LPI  __BIT(11)
+
+#define        I82579_LPI_CTRL         BME1000_REG(772, 20)
+#define        I82579_LPI_CTRL_ENABLE  __BITS(14, 13)
+#define        I82579_LPI_CTRL_EN_100  __BIT(13)
+#define        I82579_LPI_CTRL_EN_1000 __BIT(14)
+
+#define        I217_MEMPWR             BME1000_REG(772, 26)
+#define        I217_MEMPWR_DISABLE_SMB_RELEASE         0x0010
+
+#define        I217_CFGREG             BME1000_REG(772, 29)
+#define I217_CGFREG_ENABLE_MTA_RESET   0x0002
+
 #define HV_MUX_DATA_CTRL       BME1000_REG(776, 16)
 #define HV_MUX_DATA_CTRL_FORCE_SPEED   (1 << 2)
 #define HV_MUX_DATA_CTRL_GEN_TO_MAC    (1 << 10)
@@ -151,4 +165,6 @@
 #define        BM_WUC_HOST_WU_BIT      (1 << 4)
 #define        BM_WUC_ME_WU_BIT        (1 << 5)
 
+#define        I217_PROXY_CTRL         BME1000_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE   0x0080
 #endif /* _DEV_MII_INBMPHYREG_H_ */
diff -r 0ce2f7eab4dd -r 13dfbd2e644b sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Dec 12 08:28:44 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Dec 12 08:49:33 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.602 2018/11/28 08:19:19 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.603 2018/12/12 08:49:33 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -83,7 +83,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.602 2018/11/28 08:19:19 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.603 2018/12/12 08:49:33 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -723,7 +723,7 @@
 static int     wm_oem_bits_config_ich8lan(struct wm_softc *, bool);
 static void    wm_initialize_hardware_bits(struct wm_softc *);
 static uint32_t        wm_rxpbs_adjust_82580(uint32_t);
-static void    wm_reset_phy(struct wm_softc *);
+static int     wm_reset_phy(struct wm_softc *);
 static void    wm_flush_desc_rings(struct wm_softc *);
 static void    wm_reset(struct wm_softc *);
 static int     wm_add_rxbuf(struct wm_rxqueue *, int);
@@ -949,7 +949,7 @@
 static void    wm_get_hw_control(struct wm_softc *);
 static void    wm_release_hw_control(struct wm_softc *);
 static void    wm_gate_hw_phy_config_ich8lan(struct wm_softc *, bool);
-static void    wm_smbustopci(struct wm_softc *);
+static int     wm_init_phy_workarounds_pchlan(struct wm_softc *);
 static void    wm_init_manageability(struct wm_softc *);
 static void    wm_release_manageability(struct wm_softc *);
 static void    wm_get_wakeup(struct wm_softc *);
@@ -957,6 +957,7 @@
 static void    wm_enable_phy_wakeup(struct wm_softc *);
 static void    wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
 static void    wm_suspend_workarounds_ich8lan(struct wm_softc *);
+static int     wm_resume_workarounds_pchlan(struct wm_softc *);
 static void    wm_enable_wakeup(struct wm_softc *);
 static void    wm_disable_aspm(struct wm_softc *);
 /* LPLU (Low Power Link Up) */
@@ -2099,9 +2100,6 @@
                    (sc->sc_flags & WM_F_PCIX) ? "PCIX" : "PCI");
        }
 
-       /* Disable ASPM L0s and/or L1 for workaround */
-       wm_disable_aspm(sc);
-
        /* clear interesting stat counters */
        CSR_READ(sc, WMREG_COLC);
        CSR_READ(sc, WMREG_RXERRC);
@@ -2978,10 +2976,24 @@
 wm_resume(device_t self, const pmf_qual_t *qual)
 {
        struct wm_softc *sc = device_private(self);
-
-       /* Disable ASPM L0s and/or L1 for workaround */
-       wm_disable_aspm(sc);
-       wm_init_manageability(sc);
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+       if (sc->sc_type >= WM_T_PCH2)
+               wm_resume_workarounds_pchlan(sc);
+       if ((ifp->if_flags & IFF_UP) == 0) {
+               wm_reset(sc);
+               /* Non-AMT based hardware can now take control from firmware */
+               if ((sc->sc_flags & WM_F_HAS_AMT) == 0)
+                       wm_get_hw_control(sc);
+               wm_init_manageability(sc);
+       } else {
+               /*
+                * We called pmf_class_network_register(), so if_init() is
+                * automatically called when IFF_UP. wm_reset(),
+                * wm_get_hw_control() and wm_init_manageability() are called
+                * via wm_init().
+                */
+       }
 
        return true;
 }
@@ -4365,7 +4377,7 @@
  *     generic PHY reset function.
  *     Same as e1000_phy_hw_reset_generic()
  */
-static void
+static int
 wm_reset_phy(struct wm_softc *sc)
 {
        uint32_t reg;
@@ -4373,7 +4385,7 @@
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
        if (wm_phy_resetisblocked(sc))
-               return;
+               return -1;
 
        sc->phy.acquire(sc);
 
@@ -4392,6 +4404,8 @@
 
        wm_get_cfg_done(sc);
        wm_phy_post_reset(sc);
+
+       return 0;
 }
 
 /*
@@ -4893,6 +4907,9 @@
        if (sc->sc_type >= WM_T_82544)
                CSR_WRITE(sc, WMREG_WUC, 0);
 
+       if (sc->sc_type < WM_T_82575)
+               wm_disable_aspm(sc);
+
        wm_reset_mdicnfg_82580(sc);
 
        if ((sc->sc_flags & WM_F_PLL_WA_I210) != 0)
@@ -9907,7 +9924,7 @@
        if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
            || (sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT)
            || (sc->sc_type == WM_T_PCH_CNP))
-               wm_smbustopci(sc);
+               wm_init_phy_workarounds_pchlan(sc);
 
        wm_gmii_reset(sc);
 
@@ -13839,8 +13856,8 @@
        CSR_WRITE(sc, WMREG_EXTCNFCTR, reg);
 }
 
-static void
-wm_smbustopci(struct wm_softc *sc)
+static int
+wm_init_phy_workarounds_pchlan(struct wm_softc *sc)
 {
        uint32_t fwsm, reg;
        int rv = 0;
@@ -13855,8 +13872,17 @@
        wm_ulp_disable(sc);
 
        /* Acquire PHY semaphore */
-       sc->phy.acquire(sc);
-
+       rv = sc->phy.acquire(sc);
+       if (rv != 0) {
+               DPRINTF(WM_DEBUG_INIT, ("%s: %s: failed\n",
+               device_xname(sc->sc_dev), __func__));
+               return -1;
+       }
+
+       /* The MAC-PHY interconnect may be in SMBus mode.  If the PHY is
+        * inaccessible and resetting the PHY is not blocked, toggle the
+        * LANPHYPC Value bit to force the interconnect to PCIe mode.
+        */
        fwsm = CSR_READ(sc, WMREG_FWSM);
        switch (sc->sc_type) {
        case WM_T_PCH_LPT:
@@ -13865,6 +13891,9 @@
                if (wm_phy_is_accessible_pchlan(sc))
                        break;
 
+               /* Before toggling LANPHYPC, see if PHY is accessible by
+                * forcing MAC to SMBus mode first.
+                */
                reg = CSR_READ(sc, WMREG_CTRL_EXT);
                reg |= CTRL_EXT_FORCE_SMBUS;
                CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
@@ -13872,6 +13901,10 @@
                /* XXX Isn't this required??? */
                CSR_WRITE_FLUSH(sc);
 #endif
+               /* Wait 50 milliseconds for MAC to finish any retries
+                * that it might be trying to perform from previous
+                * attempts to acknowledge any phy read requests.
+                */
                delay(50 * 1000);
                /* FALLTHROUGH */
        case WM_T_PCH2:
@@ -13888,12 +13921,16 @@
                        break;
                }
 
+               /* Toggle LANPHYPC Value bit */
                wm_toggle_lanphypc_pch_lpt(sc);
 
                if (sc->sc_type >= WM_T_PCH_LPT) {
                        if (wm_phy_is_accessible_pchlan(sc) == true)
                                break;
 
+                       /* Toggling LANPHYPC brings the PHY out of SMBus mode
+                        * so ensure that the MAC is also out of SMBus mode
+                        */
                        reg = CSR_READ(sc, WMREG_CTRL_EXT);
                        reg &= ~CTRL_EXT_FORCE_SMBUS;
                        CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
@@ -13911,23 +13948,38 @@
        sc->phy.release(sc);
 
        if (rv == 0) {
+               /* Check to see if able to reset PHY.  Print error if not */
                if (wm_phy_resetisblocked(sc)) {
                        printf("XXX reset is blocked(4)\n");
                        goto out;
                }
-               wm_reset_phy(sc);
+
+               /* Reset the PHY before any access to it.  Doing so, ensures
+                * that the PHY is in a known good state before we read/write
+                * PHY registers.  The generic reset is sufficient here,
+                * because we haven't determined the PHY type yet.
+                */
+               if (wm_reset_phy(sc) != 0)
+                       goto out;
+
+               /* On a successful reset, possibly need to wait for the PHY
+                * to quiesce to an accessible state before returning control
+                * to the calling function.  If the PHY does not quiesce, then
+                * return E1000E_BLK_PHY_RESET, as this is the condition that
+                *  the PHY is in.
+                */
                if (wm_phy_resetisblocked(sc))
                        printf("XXX reset is blocked(4)\n");
        }
 
 out:
-       /*
-        * Ungate automatic PHY configuration by hardware on non-managed 82579
-        */
+       /* Ungate automatic PHY configuration on non-managed 82579 */
        if ((sc->sc_type == WM_T_PCH2) && ((fwsm & FWSM_FW_VALID) == 0)) {
                delay(10*1000);
                wm_gate_hw_phy_config_ich8lan(sc, false);
        }
+
+       return 0;
 }
 
 static void
@@ -14066,7 +14118,12 @@
        }
 
        /* Acquire semaphore */
-       sc->phy.acquire(sc);
+       rv = sc->phy.acquire(sc);
+       if (rv != 0) {
+               DPRINTF(WM_DEBUG_INIT, ("%s: %s: failed\n",
+               device_xname(sc->sc_dev), __func__));
+               goto release;
+       }
 
        /* Toggle LANPHYPC */
        wm_toggle_lanphypc_pch_lpt(sc);
@@ -14269,6 +14326,73 @@
        }
 }
 
+/*
+ *  wm_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ *  @hw: pointer to the HW structure
+ *



Home | Main Index | Thread Index | Old Index