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/7e2da29adbd3
branches: trunk
changeset: 995218:7e2da29adbd3
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 fb5818f1a58f -r 7e2da29adbd3 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 fb5818f1a58f -r 7e2da29adbd3 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