Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Sync wm_smbustopci() with Linux and FreeBSD. This ch...



details:   https://anonhg.NetBSD.org/src/rev/96202cf81b89
branches:  trunk
changeset: 348930:96202cf81b89
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Wed Nov 16 08:56:17 2016 +0000

description:
Sync wm_smbustopci() with Linux and FreeBSD. This change effects PCH and
newer devices.

diffstat:

 sys/dev/mii/inbmphyreg.h |   19 ++-
 sys/dev/pci/if_wm.c      |  312 +++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/pci/if_wmreg.h   |   18 ++-
 3 files changed, 324 insertions(+), 25 deletions(-)

diffs (truncated from 515 to 300 lines):

diff -r 36eb1296e965 -r 96202cf81b89 sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h  Wed Nov 16 08:14:39 2016 +0000
+++ b/sys/dev/mii/inbmphyreg.h  Wed Nov 16 08:56:17 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: inbmphyreg.h,v 1.8 2016/11/08 10:37:39 msaitoh Exp $   */
+/*     $NetBSD: inbmphyreg.h,v 1.9 2016/11/16 08:56:17 msaitoh Exp $   */
 /*******************************************************************************
 Copyright (c) 2001-2005, Intel Corporation 
 All rights reserved.
@@ -96,6 +96,12 @@
 
 #define        BM_PORT_GEN_CFG         BME1000_REG(BM_PORT_CTRL_PAGE, 17)
 
+#define        CV_SMB_CTRL             BME1000_REG(BM_PORT_CTRL_PAGE, 23)
+#define        CV_SMB_CTRL_FORCE_SMBUS __BIT(0)
+
+#define        HV_PM_CTRL              BME1000_REG(770, 17)
+#define        HV_PM_CTRL_K1_ENA       __BIT(14)
+
 #define        IGP3_KMRN_DIAG          BME1000_REG(770, 19)
 #define        IGP3_KMRN_DIAG_PCS_LOCK_LOSS    (1 << 1)
 
@@ -103,6 +109,17 @@
 #define HV_MUX_DATA_CTRL_FORCE_SPEED   (1 << 2)
 #define HV_MUX_DATA_CTRL_GEN_TO_MAC    (1 << 10)
 
+#define I218_ULP_CONFIG1       BME1000_REG(779, 16)
+#define I218_ULP_CONFIG1_START         __BIT(0)
+#define I218_ULP_CONFIG1_IND           __BIT(2)
+#define I218_ULP_CONFIG1_STICKY_ULP    __BIT(4)
+#define I218_ULP_CONFIG1_INBAND_EXIT   __BIT(5)
+#define I218_ULP_CONFIG1_WOL_HOST      __BIT(6)
+#define I218_ULP_CONFIG1_RESET_TO_SMBUS        __BIT(8)
+#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC __BIT(10)
+#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST __BIT(11)
+#define I218_ULP_CONFIG1_DIS_SMB_PERST __BIT(12)
+
 #define        BM_WUC_PAGE             800
 #define        BM_WUC                  BME1000_REG(BM_WUC_PAGE, 1)
 #define        BM_WUC_ADDRESS_OPCODE   0x11
diff -r 36eb1296e965 -r 96202cf81b89 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Nov 16 08:14:39 2016 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Nov 16 08:56:17 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.446 2016/11/16 08:14:39 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.447 2016/11/16 08:56:17 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.446 2016/11/16 08:14:39 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.447 2016/11/16 08:56:17 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -396,6 +396,7 @@
 struct wm_phyop {
        int (*acquire)(struct wm_softc *);
        void (*release)(struct wm_softc *);
+       int reset_delay_us;
 };
 
 /*
@@ -637,6 +638,7 @@
 static void    wm_get_cfg_done(struct wm_softc *);
 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 void    wm_flush_desc_rings(struct wm_softc *);
 static void    wm_reset(struct wm_softc *);
 static int     wm_add_rxbuf(struct wm_rxqueue *, int);
@@ -840,6 +842,7 @@
 static void    wm_init_manageability(struct wm_softc *);
 static void    wm_release_manageability(struct wm_softc *);
 static void    wm_get_wakeup(struct wm_softc *);
+static void    wm_ulp_disable(struct wm_softc *);
 static void    wm_enable_phy_wakeup(struct wm_softc *);
 static void    wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
 static void    wm_enable_wakeup(struct wm_softc *);
@@ -862,6 +865,8 @@
 static void    wm_configure_k1_ich8lan(struct wm_softc *, int);
 static void    wm_reset_init_script_82575(struct wm_softc *);
 static void    wm_reset_mdicnfg_82580(struct wm_softc *);
+static bool    wm_phy_is_accessible_pchlan(struct wm_softc *);
+static void    wm_toggle_lanphypc_pch_lpt(struct wm_softc *);
 static int     wm_platform_pm_pch_lpt(struct wm_softc *, bool);
 static void    wm_pll_workaround_i210(struct wm_softc *);
 
@@ -1630,6 +1635,7 @@
        /* Set default function pointers */
        sc->phy.acquire = wm_get_null;
        sc->phy.release = wm_put_null;
+       sc->phy.reset_delay_us = (sc->sc_type >= WM_T_82571) ? 100 : 10000;
 
        if (sc->sc_type < WM_T_82543) {
                if (sc->sc_rev < 2) {
@@ -3727,6 +3733,40 @@
        return rv;
 }
 
+/*
+ * wm_reset_phy:
+ *
+ *     generic PHY reset function.
+ *     Same as e1000_phy_hw_reset_generic()
+ */
+static void
+wm_reset_phy(struct wm_softc *sc)
+{
+       uint32_t reg;
+
+       DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+               device_xname(sc->sc_dev), __func__));
+       if (wm_phy_resetisblocked(sc))
+               return;
+
+       sc->phy.acquire(sc);
+
+       reg = CSR_READ(sc, WMREG_CTRL);
+       CSR_WRITE(sc, WMREG_CTRL, reg | CTRL_PHY_RESET);
+       CSR_WRITE_FLUSH(sc);
+
+       delay(sc->phy.reset_delay_us);
+
+       CSR_WRITE(sc, WMREG_CTRL, reg);
+       CSR_WRITE_FLUSH(sc);
+
+       delay(150);
+       
+       sc->phy.release(sc);
+
+       wm_get_cfg_done(sc);
+}
+
 static void
 wm_flush_desc_rings(struct wm_softc *sc)
 {
@@ -11902,6 +11942,7 @@
 wm_smbustopci(struct wm_softc *sc)
 {
        uint32_t fwsm, reg;
+       int rv = 0;
 
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
@@ -11909,46 +11950,82 @@
        /* Gate automatic PHY configuration by hardware on non-managed 82579 */
        wm_gate_hw_phy_config_ich8lan(sc, true);
 
+       /* Disable ULP */
+       wm_ulp_disable(sc);
+
        /* Acquire PHY semaphore */
        sc->phy.acquire(sc);
 
        fwsm = CSR_READ(sc, WMREG_FWSM);
-       if (((fwsm & FWSM_FW_VALID) == 0)
-           && ((wm_phy_resetisblocked(sc) == false))) {
-               if (sc->sc_type >= WM_T_PCH_LPT) {
-                       reg = CSR_READ(sc, WMREG_CTRL_EXT);
-                       reg |= CTRL_EXT_FORCE_SMBUS;
-                       CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
-                       CSR_WRITE_FLUSH(sc);
-                       delay(50*1000);
-               }
-
-               /* Toggle LANPHYPC */
-               sc->sc_ctrl |= CTRL_LANPHYPC_OVERRIDE;
-               sc->sc_ctrl &= ~CTRL_LANPHYPC_VALUE;
-               CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+       switch (sc->sc_type) {
+       case WM_T_PCH_LPT:
+       case WM_T_PCH_SPT:
+               if (wm_phy_is_accessible_pchlan(sc))
+                       break;
+
+               reg = CSR_READ(sc, WMREG_CTRL_EXT);
+               reg |= CTRL_EXT_FORCE_SMBUS;
+               CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+#if 0
+               /* XXX Isn't this required??? */
                CSR_WRITE_FLUSH(sc);
-               delay(1000);
-               sc->sc_ctrl &= ~CTRL_LANPHYPC_OVERRIDE;
-               CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-               CSR_WRITE_FLUSH(sc);
-               delay(50*1000);
+#endif
+               delay(50 * 1000);
+               /* FALLTHROUGH */
+       case WM_T_PCH2:
+               if (wm_phy_is_accessible_pchlan(sc) == true)
+                       break;
+               /* FALLTHROUGH */
+       case WM_T_PCH:
+               if ((sc->sc_type == WM_T_PCH))
+                       if ((fwsm & FWSM_FW_VALID) != 0)
+                               break;
+
+               if (wm_phy_resetisblocked(sc) == true) {
+                       printf("XXX reset is blocked(3)\n");
+                       break;
+               }
+
+               wm_toggle_lanphypc_pch_lpt(sc);
 
                if (sc->sc_type >= WM_T_PCH_LPT) {
+                       if (wm_phy_is_accessible_pchlan(sc) == true)
+                               break;
+
                        reg = CSR_READ(sc, WMREG_CTRL_EXT);
                        reg &= ~CTRL_EXT_FORCE_SMBUS;
                        CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
-               }
+
+                       if (wm_phy_is_accessible_pchlan(sc) == true)
+                               break;
+                       rv = -1;
+               }
+               break;
+       default:
+               break;
        }
 
        /* Release semaphore */
        sc->phy.release(sc);
 
+       if (rv == 0) {
+               if (wm_phy_resetisblocked(sc)) {
+                       printf("XXX reset is blocked(4)\n");
+                       goto out;
+               }
+               wm_reset_phy(sc);
+               if (wm_phy_resetisblocked(sc))
+                       printf("XXX reset is blocked(4)\n");
+       }
+
+out:
        /*
         * Ungate automatic PHY configuration by hardware on non-managed 82579
         */
-       if ((sc->sc_type == WM_T_PCH2) && ((fwsm & FWSM_FW_VALID) == 0))
+       if ((sc->sc_type == WM_T_PCH2) && ((fwsm & FWSM_FW_VALID) == 0)) {
+               delay(10*1000);
                wm_gate_hw_phy_config_ich8lan(sc, false);
+       }
 }
 
 static void
@@ -12051,6 +12128,102 @@
         */
 }
 
+/*
+ * Unconfigure Ultra Low Power mode.
+ * Only for I217 and newer (see below).
+ */
+static void
+wm_ulp_disable(struct wm_softc *sc)
+{
+       uint32_t reg;
+       int i = 0;
+
+       DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+               device_xname(sc->sc_dev), __func__));
+       /* Exclude old devices */
+       if ((sc->sc_type < WM_T_PCH_LPT)
+           || (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I217_LM)
+           || (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I217_V)
+           || (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM2)
+           || (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V2))
+               return;
+
+       if ((CSR_READ(sc, WMREG_FWSM) & FWSM_FW_VALID) != 0) {
+               /* Request ME un-configure ULP mode in the PHY */
+               reg = CSR_READ(sc, WMREG_H2ME);
+               reg &= ~H2ME_ULP;
+               reg |= H2ME_ENFORCE_SETTINGS;
+               CSR_WRITE(sc, WMREG_H2ME, reg);
+
+               /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */
+               while ((CSR_READ(sc, WMREG_FWSM) & FWSM_ULP_CFG_DONE) != 0) {
+                       if (i++ == 30) {
+                               printf("%s timed out\n", __func__);
+                               return;
+                       }
+                       delay(10 * 1000);
+               }
+               reg = CSR_READ(sc, WMREG_H2ME);
+               reg &= ~H2ME_ENFORCE_SETTINGS;
+               CSR_WRITE(sc, WMREG_H2ME, reg);
+
+               return;
+       }
+
+       /* Acquire semaphore */
+       sc->phy.acquire(sc);



Home | Main Index | Thread Index | Old Index