Module Name: src
Committed By: martin
Date: Thu Jan 31 06:43:48 UTC 2019
Modified Files:
src/sys/dev/mii [netbsd-8]: inbmphyreg.h
src/sys/dev/pci [netbsd-8]: if_wm.c if_wmreg.h if_wmvar.h
Log Message:
Pull up the following, requested by msaitoh in ticket #1179:
sys/dev/pci/if_wm.c 1.603-1.605,1.607-1.611,
1.613,1.615,1.618-1.620
via patch
sys/dev/pci/if_wmreg.h 1.110-1.111
sys/dev/pci/if_wmvar.h 1.40-1.42
sys/dev/mii/inbmphyreg.h 1.13-1.15
- 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().
- Print CLSEM workaround bit correctly.
- Fix availability detection of WoL on some chips.
- Print the WUS (WakeUp Status) register bits when resume.
- Don't setup WoL on non-WoL capable port.
- Setup PHY wakeup feature on PCH and newer. Tested on Thinkpad X220.
- Remove an extra register read in
wm_kmrn_lock_loss_workaround_ich8lan().
- Don't leave the MDICNFG register modified when the Power Management
capability offset can't get.
- Reduce indent level of wm_linkintr_gmii(). No functional change.
- 80003's SERDES is not the same as 82575's but the same as legacy
devices. Use the old methods on 80003.
- Use __nothing for null DPRINTF().
- Rename functions. Add comment.
To generate a diff of this commit:
cvs rdiff -u -r1.9.8.3 -r1.9.8.4 src/sys/dev/mii/inbmphyreg.h
cvs rdiff -u -r1.508.4.28 -r1.508.4.29 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.98.6.6 -r1.98.6.7 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.33.6.3 -r1.33.6.4 src/sys/dev/pci/if_wmvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/mii/inbmphyreg.h
diff -u src/sys/dev/mii/inbmphyreg.h:1.9.8.3 src/sys/dev/mii/inbmphyreg.h:1.9.8.4
--- src/sys/dev/mii/inbmphyreg.h:1.9.8.3 Tue Dec 4 11:21:32 2018
+++ src/sys/dev/mii/inbmphyreg.h Thu Jan 31 06:43:48 2019
@@ -1,6 +1,6 @@
-/* $NetBSD: inbmphyreg.h,v 1.9.8.3 2018/12/04 11:21:32 martin Exp $ */
+/* $NetBSD: inbmphyreg.h,v 1.9.8.4 2019/01/31 06:43:48 martin Exp $ */
/*******************************************************************************
-Copyright (c) 2001-2005, Intel Corporation
+Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,16 @@ POSSIBILITY OF SUCH DAMAGE.
#define _DEV_MII_INBMPHYREG_H_
/* Bits...
- * 15-5: page
- * 4-0: register offset
+ * 31-16: register offset (high)
+ * 15-5: page
+ * 4-0: register offset (low)
*/
-#define BME1000_PAGE_SHIFT 5
+#define BME1000_PAGE_SHIFT 5
+#define BM_PHY_UPPER_SHIFT 21
#define BME1000_REG(page, reg) \
- (((page) << BME1000_PAGE_SHIFT) | ((reg) & MII_ADDRMASK))
+ (((reg) & MII_ADDRMASK) | \
+ (((page) & 0xffff) << BME1000_PAGE_SHIFT) | \
+ (((reg) & ~MII_ADDRMASK) << (BM_PHY_UPPER_SHIFT - BME1000_PAGE_SHIFT)))
#define BME1000_MAX_MULTI_PAGE_REG 0xf /* Registers equal on all pages */
@@ -52,7 +56,7 @@ POSSIBILITY OF SUCH DAMAGE.
((uint16_t)(((offset) >> BME1000_PAGE_SHIFT) & 0xffff))
#define BM_PHY_REG_NUM(offset) \
((uint16_t)((offset) & MII_ADDRMASK) \
- | (((offset) >> (21 - BME1000_PAGE_SHIFT)) & ~MII_ADDRMASK))
+ | (((offset) >> (BM_PHY_UPPER_SHIFT - BME1000_PAGE_SHIFT)) & ~MII_ADDRMASK))
/* BME1000 Specific Registers */
#define BME1000_PHY_SPEC_CTRL BME1000_REG(0, 16) /* PHY Specific Control */
@@ -126,6 +130,20 @@ POSSIBILITY OF SUCH DAMAGE.
#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)
@@ -142,6 +160,16 @@ POSSIBILITY OF SUCH DAMAGE.
#define I218_ULP_CONFIG1_DIS_SMB_PERST __BIT(12)
#define BM_WUC_PAGE 800
+
+#define BM_RCTL BME1000_REG(BM_WUC_PAGE, 0)
+#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */
+#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */
+#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */
+#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */
+#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */
+#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
+#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
+
#define BM_WUC BME1000_REG(BM_WUC_PAGE, 1)
#define BM_WUC_ADDRESS_OPCODE 0x11
#define BM_WUC_DATA_OPCODE 0x12
@@ -151,4 +179,15 @@ POSSIBILITY OF SUCH DAMAGE.
#define BM_WUC_HOST_WU_BIT (1 << 4)
#define BM_WUC_ME_WU_BIT (1 << 5)
+#define BM_WUFC BME1000_REG(BM_WUC_PAGE, 2)
+
+#define I217_PROXY_CTRL BME1000_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
+
+#define BM_RAR_L(_i) (BME1000_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
+#define BM_RAR_M(_i) (BME1000_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
+#define BM_RAR_H(_i) (BME1000_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
+#define BM_RAR_CTRL(_i) (BME1000_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
+#define BM_MTA(_i) (BME1000_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
+
#endif /* _DEV_MII_INBMPHYREG_H_ */
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.508.4.28 src/sys/dev/pci/if_wm.c:1.508.4.29
--- src/sys/dev/pci/if_wm.c:1.508.4.28 Tue Dec 18 18:24:09 2018
+++ src/sys/dev/pci/if_wm.c Thu Jan 31 06:43:48 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.508.4.28 2018/12/18 18:24:09 martin Exp $ */
+/* $NetBSD: if_wm.c,v 1.508.4.29 2019/01/31 06:43:48 martin 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.508.4.28 2018/12/18 18:24:09 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.508.4.29 2019/01/31 06:43:48 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -159,7 +159,7 @@ int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX
#define DPRINTF(x, y) if (wm_debug & (x)) printf y
#else
-#define DPRINTF(x, y) /* nothing */
+#define DPRINTF(x, y) __nothing
#endif /* WM_DEBUG */
#ifdef NET_MPSAFE
@@ -710,6 +710,7 @@ static uint16_t wm_check_alt_mac_addr(st
static int wm_read_mac_addr(struct wm_softc *, uint8_t *);
static void wm_set_ral(struct wm_softc *, const uint8_t *, int);
static uint32_t wm_mchash(struct wm_softc *, const uint8_t *);
+static int wm_rar_count(struct wm_softc *);
static void wm_set_filter(struct wm_softc *);
/* Reset and init related */
static void wm_set_vlan(struct wm_softc *);
@@ -723,7 +724,7 @@ static void wm_init_lcd_from_nvm(struct
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);
@@ -829,7 +830,10 @@ static int wm_gmii_i80003_readreg(device
static void wm_gmii_i80003_writereg(device_t, int, int, int);
static int wm_gmii_bm_readreg(device_t, int, int);
static void wm_gmii_bm_writereg(device_t, int, int, int);
-static void wm_access_phy_wakeup_reg_bm(device_t, int, int16_t *, int);
+static int wm_enable_phy_wakeup_reg_access_bm(device_t, uint16_t *);
+static int wm_disable_phy_wakeup_reg_access_bm(device_t, uint16_t *);
+static int wm_access_phy_wakeup_reg_bm(device_t, int, int16_t *, int,
+ bool);
static int wm_gmii_hv_readreg(device_t, int, int);
static int wm_gmii_hv_readreg_locked(device_t, int, int, uint16_t *);
static void wm_gmii_hv_writereg(device_t, int, int, int);
@@ -949,14 +953,15 @@ static bool wm_phy_resetisblocked(struct
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 *);
static int wm_ulp_disable(struct wm_softc *);
-static void wm_enable_phy_wakeup(struct wm_softc *);
+static int 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) */
@@ -970,8 +975,9 @@ static void wm_set_eee_i350(struct wm_so
*/
static void wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *);
static void wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
-static void wm_hv_phy_workaround_ich8lan(struct wm_softc *);
-static void wm_lv_phy_workaround_ich8lan(struct wm_softc *);
+static void wm_hv_phy_workarounds_ich8lan(struct wm_softc *);
+static void wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *);
+static void wm_lv_phy_workarounds_ich8lan(struct wm_softc *);
static int wm_k1_workaround_lpt_lp(struct wm_softc *, bool);
static int wm_k1_gig_workaround_hv(struct wm_softc *, int);
static int wm_k1_workaround_lv(struct wm_softc *);
@@ -2099,9 +2105,6 @@ alloc_retry:
(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);
@@ -2381,6 +2384,25 @@ alloc_retry:
*/
wm_gmii_setup_phytype(sc, 0, 0);
+ /* Check for WM_F_WOL on some chips before wm_reset() */
+ switch (sc->sc_type) {
+ case WM_T_ICH8:
+ case WM_T_ICH9:
+ case WM_T_ICH10:
+ case WM_T_PCH:
+ case WM_T_PCH2:
+ case WM_T_PCH_LPT:
+ case WM_T_PCH_SPT:
+ case WM_T_PCH_CNP:
+ apme_mask = WUC_APME;
+ eeprom_data = CSR_READ(sc, WMREG_WUC);
+ if ((eeprom_data & apme_mask) != 0)
+ sc->sc_flags |= WM_F_WOL;
+ break;
+ default:
+ break;
+ }
+
/* Reset the chip to a known state. */
wm_reset(sc);
@@ -2482,16 +2504,22 @@ alloc_retry:
case WM_T_82574:
case WM_T_82583:
case WM_T_80003:
- default:
+ case WM_T_82575:
+ case WM_T_82576:
apme_mask = NVM_CFG3_APME;
wm_nvm_read(sc, (sc->sc_funcid == 1) ? NVM_OFF_CFG3_PORTB
: NVM_OFF_CFG3_PORTA, 1, &eeprom_data);
break;
- case WM_T_82575:
- case WM_T_82576:
case WM_T_82580:
case WM_T_I350:
- case WM_T_I354: /* XXX ok? */
+ case WM_T_I354:
+ case WM_T_I210:
+ case WM_T_I211:
+ apme_mask = NVM_CFG3_APME;
+ wm_nvm_read(sc,
+ NVM_OFF_LAN_FUNC_82580(sc->sc_funcid) + NVM_OFF_CFG3_PORTA,
+ 1, &eeprom_data);
+ break;
case WM_T_ICH8:
case WM_T_ICH9:
case WM_T_ICH10:
@@ -2500,16 +2528,54 @@ alloc_retry:
case WM_T_PCH_LPT:
case WM_T_PCH_SPT:
case WM_T_PCH_CNP:
- /* XXX The funcid should be checked on some devices */
- apme_mask = WUC_APME;
- eeprom_data = CSR_READ(sc, WMREG_WUC);
+ /* Already checked before wm_reset () */
+ apme_mask = eeprom_data = 0;
+ break;
+ default: /* XXX 82540 */
+ apme_mask = NVM_CFG3_APME;
+ wm_nvm_read(sc, NVM_OFF_CFG3_PORTA, 1, &eeprom_data);
break;
}
-
/* Check for WM_F_WOL flag after the setting of the EEPROM stuff */
if ((eeprom_data & apme_mask) != 0)
sc->sc_flags |= WM_F_WOL;
+ /*
+ * We have the eeprom settings, now apply the special cases
+ * where the eeprom may be wrong or the board won't support
+ * wake on lan on a particular port
+ */
+ switch (sc->sc_pcidevid) {
+ case PCI_PRODUCT_INTEL_82546GB_PCIE:
+ sc->sc_flags &= ~WM_F_WOL;
+ break;
+ case PCI_PRODUCT_INTEL_82546EB_FIBER:
+ case PCI_PRODUCT_INTEL_82546GB_FIBER:
+ /* Wake events only supported on port A for dual fiber
+ * regardless of eeprom setting */
+ if (sc->sc_funcid == 1)
+ sc->sc_flags &= ~WM_F_WOL;
+ break;
+ case PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3:
+ /* if quad port adapter, disable WoL on all but port A */
+ if (sc->sc_funcid != 0)
+ sc->sc_flags &= ~WM_F_WOL;
+ break;
+ case PCI_PRODUCT_INTEL_82571EB_FIBER:
+ /* Wake events only supported on port A for dual fiber
+ * regardless of eeprom setting */
+ if (sc->sc_funcid == 1)
+ sc->sc_flags &= ~WM_F_WOL;
+ break;
+ case PCI_PRODUCT_INTEL_82571EB_QUAD_COPPER:
+ case PCI_PRODUCT_INTEL_82571EB_QUAD_FIBER:
+ case PCI_PRODUCT_INTEL_82571GB_QUAD_COPPER:
+ /* if quad port adapter, disable WoL on all but port A */
+ if (sc->sc_funcid != 0)
+ sc->sc_flags &= ~WM_F_WOL;
+ break;
+ }
+
if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
/* Check NVM for autonegotiation */
if (wm_nvm_read(sc, NVM_OFF_COMPAT, 1, &nvmword) == 0) {
@@ -2872,7 +2938,7 @@ alloc_retry:
aprint_error_dev(self, "couldn't establish power handler\n");
sc->sc_flags |= WM_F_ATTACHED;
- out:
+out:
return;
}
@@ -2978,10 +3044,33 @@ static bool
wm_resume(device_t self, const pmf_qual_t *qual)
{
struct wm_softc *sc = device_private(self);
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ pcireg_t reg;
+ char buf[256];
- /* Disable ASPM L0s and/or L1 for workaround */
- wm_disable_aspm(sc);
- wm_init_manageability(sc);
+ reg = CSR_READ(sc, WMREG_WUS);
+ if (reg != 0) {
+ snprintb(buf, sizeof(buf), WUS_FLAGS, reg);
+ device_printf(sc->sc_dev, "wakeup status %s\n", buf);
+ CSR_WRITE(sc, WMREG_WUS, 0xffffffff); /* W1C */
+ }
+
+ 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;
}
@@ -3149,7 +3238,7 @@ wm_tick(void *arg)
if (sc->sc_flags & WM_F_HAS_MII)
mii_tick(&sc->sc_mii);
- else if ((sc->sc_type >= WM_T_82575)
+ else if ((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211)
&& (sc->sc_mediatype == WM_MEDIATYPE_SERDES))
wm_serdes_tick(sc);
else
@@ -3482,6 +3571,50 @@ wm_mchash(struct wm_softc *sc, const uin
}
/*
+ *
+ *
+ */
+static int
+wm_rar_count(struct wm_softc *sc)
+{
+ int size;
+
+ switch (sc->sc_type) {
+ case WM_T_ICH8:
+ size = WM_RAL_TABSIZE_ICH8 -1;
+ break;
+ case WM_T_ICH9:
+ case WM_T_ICH10:
+ case WM_T_PCH:
+ size = WM_RAL_TABSIZE_ICH8;
+ break;
+ case WM_T_PCH2:
+ size = WM_RAL_TABSIZE_PCH2;
+ break;
+ case WM_T_PCH_LPT:
+ case WM_T_PCH_SPT:
+ case WM_T_PCH_CNP:
+ size = WM_RAL_TABSIZE_PCH_LPT;
+ break;
+ case WM_T_82575:
+ size = WM_RAL_TABSIZE_82575;
+ break;
+ case WM_T_82576:
+ case WM_T_82580:
+ size = WM_RAL_TABSIZE_82576;
+ break;
+ case WM_T_I350:
+ case WM_T_I354:
+ size = WM_RAL_TABSIZE_I350;
+ break;
+ default:
+ size = WM_RAL_TABSIZE;
+ }
+
+ return size;
+}
+
+/*
* wm_set_filter:
*
* Set up the receive filter.
@@ -3518,24 +3651,7 @@ wm_set_filter(struct wm_softc *sc)
* Set the station address in the first RAL slot, and
* clear the remaining slots.
*/
- if (sc->sc_type == WM_T_ICH8)
- size = WM_RAL_TABSIZE_ICH8 -1;
- else if ((sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10)
- || (sc->sc_type == WM_T_PCH))
- size = WM_RAL_TABSIZE_ICH8;
- else if (sc->sc_type == WM_T_PCH2)
- size = WM_RAL_TABSIZE_PCH2;
- else if ((sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT)
- || (sc->sc_type == WM_T_PCH_CNP))
- size = WM_RAL_TABSIZE_PCH_LPT;
- else if (sc->sc_type == WM_T_82575)
- size = WM_RAL_TABSIZE_82575;
- else if ((sc->sc_type == WM_T_82576) || (sc->sc_type == WM_T_82580))
- size = WM_RAL_TABSIZE_82576;
- else if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
- size = WM_RAL_TABSIZE_I350;
- else
- size = WM_RAL_TABSIZE;
+ size = wm_rar_count(sc);
wm_set_ral(sc, CLLADDR(ifp->if_sadl), 0);
if ((sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT)
@@ -3815,10 +3931,9 @@ wm_get_cfg_done(struct wm_softc *sc)
break;
delay(1000);
}
- if (i >= WM_PHY_CFG_TIMEOUT) {
+ if (i >= WM_PHY_CFG_TIMEOUT)
DPRINTF(WM_DEBUG_GMII, ("%s: %s failed\n",
device_xname(sc->sc_dev), __func__));
- }
break;
case WM_T_ICH8:
case WM_T_ICH9:
@@ -3866,9 +3981,9 @@ wm_phy_post_reset(struct wm_softc *sc)
/* Perform any necessary post-reset workarounds */
if (sc->sc_type == WM_T_PCH)
- wm_hv_phy_workaround_ich8lan(sc);
+ wm_hv_phy_workarounds_ich8lan(sc);
else if (sc->sc_type == WM_T_PCH2)
- wm_lv_phy_workaround_ich8lan(sc);
+ wm_lv_phy_workarounds_ich8lan(sc);
/* Clear the host wakeup bit after lcd reset */
if (sc->sc_type >= WM_T_PCH) {
@@ -3927,11 +4042,10 @@ wm_write_smbus_addr(struct wm_softc *sc)
HV_SMB_ADDR_FREQ_LOW);
phy_data |= __SHIFTIN((freq & 0x02) != 0,
HV_SMB_ADDR_FREQ_HIGH);
- } else {
+ } else
DPRINTF(WM_DEBUG_INIT,
("%s: %s Unsupported SMB frequency in PHY\n",
device_xname(sc->sc_dev), __func__));
- }
}
return wm_gmii_hv_writereg_locked(sc->sc_dev, 2, HV_SMB_ADDR,
@@ -4365,7 +4479,7 @@ wm_rxpbs_adjust_82580(uint32_t val)
* 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 +4487,7 @@ wm_reset_phy(struct wm_softc *sc)
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 +4506,8 @@ wm_reset_phy(struct wm_softc *sc)
wm_get_cfg_done(sc);
wm_phy_post_reset(sc);
+
+ return 0;
}
/*
@@ -4893,6 +5009,9 @@ wm_reset(struct wm_softc *sc)
if (sc->sc_type >= WM_T_82544)
CSR_WRITE(sc, WMREG_WUC, 0);
+ if (sc->sc_type < WM_T_82575)
+ wm_disable_aspm(sc); /* Workaround for some chips */
+
wm_reset_mdicnfg_82580(sc);
if ((sc->sc_flags & WM_F_PLL_WA_I210) != 0)
@@ -5961,7 +6080,7 @@ wm_init_locked(struct ifnet *ifp)
*/
sc->sc_mchash_type = 0;
sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_DPF
- | RCTL_MO(sc->sc_mchash_type);
+ | __SHIFTIN(sc->sc_mchash_type, RCTL_MO);
/*
* 82574 use one buffer extended Rx descriptor.
@@ -8782,133 +8901,135 @@ wm_rxeof(struct wm_rxqueue *rxq, u_int l
static void
wm_linkintr_gmii(struct wm_softc *sc, uint32_t icr)
{
+ uint32_t status, reg;
+ bool link;
KASSERT(WM_CORE_LOCKED(sc));
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
__func__));
- if (icr & ICR_LSC) {
- uint32_t status = CSR_READ(sc, WMREG_STATUS);
- uint32_t reg;
- bool link;
-
- link = status & STATUS_LU;
- if (link) {
- DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n",
- device_xname(sc->sc_dev),
- (status & STATUS_FD) ? "FDX" : "HDX"));
- } else {
- DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n",
+ if ((icr & ICR_LSC) == 0) {
+ if (icr & ICR_RXSEQ)
+ DPRINTF(WM_DEBUG_LINK,
+ ("%s: LINK Receive sequence error\n",
device_xname(sc->sc_dev)));
- }
- if ((sc->sc_type == WM_T_ICH8) && (link == false))
- wm_gig_downshift_workaround_ich8lan(sc);
-
- if ((sc->sc_type == WM_T_ICH8)
- && (sc->sc_phytype == WMPHY_IGP_3)) {
- wm_kmrn_lock_loss_workaround_ich8lan(sc);
- }
- DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> mii_pollstat\n",
+ return;
+ }
+ /* Link status changed */
+ status = CSR_READ(sc, WMREG_STATUS);
+ link = status & STATUS_LU;
+ if (link) {
+ DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n",
+ device_xname(sc->sc_dev),
+ (status & STATUS_FD) ? "FDX" : "HDX"));
+ } else {
+ DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n",
device_xname(sc->sc_dev)));
- mii_pollstat(&sc->sc_mii);
- if (sc->sc_type == WM_T_82543) {
- int miistatus, active;
-
- /*
- * With 82543, we need to force speed and
- * duplex on the MAC equal to what the PHY
- * speed and duplex configuration is.
- */
- miistatus = sc->sc_mii.mii_media_status;
+ }
+ if ((sc->sc_type == WM_T_ICH8) && (link == false))
+ wm_gig_downshift_workaround_ich8lan(sc);
- if (miistatus & IFM_ACTIVE) {
- active = sc->sc_mii.mii_media_active;
- sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
- switch (IFM_SUBTYPE(active)) {
- case IFM_10_T:
- sc->sc_ctrl |= CTRL_SPEED_10;
- break;
- case IFM_100_TX:
- sc->sc_ctrl |= CTRL_SPEED_100;
- break;
- case IFM_1000_T:
- sc->sc_ctrl |= CTRL_SPEED_1000;
- break;
- default:
- /*
- * fiber?
- * Shoud not enter here.
- */
- printf("unknown media (%x)\n", active);
- break;
- }
- if (active & IFM_FDX)
- sc->sc_ctrl |= CTRL_FD;
- CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
- }
- } else if (sc->sc_type == WM_T_PCH) {
- wm_k1_gig_workaround_hv(sc,
- ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
- }
+ if ((sc->sc_type == WM_T_ICH8)
+ && (sc->sc_phytype == WMPHY_IGP_3)) {
+ wm_kmrn_lock_loss_workaround_ich8lan(sc);
+ }
+ DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> mii_pollstat\n",
+ device_xname(sc->sc_dev)));
+ mii_pollstat(&sc->sc_mii);
+ if (sc->sc_type == WM_T_82543) {
+ int miistatus, active;
/*
- * I217 Packet Loss issue:
- * ensure that FEXTNVM4 Beacon Duration is set correctly
- * on power up.
- * Set the Beacon Duration for I217 to 8 usec
+ * With 82543, we need to force speed and
+ * duplex on the MAC equal to what the PHY
+ * speed and duplex configuration is.
*/
- if (sc->sc_type >= WM_T_PCH_LPT) {
- reg = CSR_READ(sc, WMREG_FEXTNVM4);
- reg &= ~FEXTNVM4_BEACON_DURATION;
- reg |= FEXTNVM4_BEACON_DURATION_8US;
- CSR_WRITE(sc, WMREG_FEXTNVM4, reg);
+ miistatus = sc->sc_mii.mii_media_status;
+
+ if (miistatus & IFM_ACTIVE) {
+ active = sc->sc_mii.mii_media_active;
+ sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
+ switch (IFM_SUBTYPE(active)) {
+ case IFM_10_T:
+ sc->sc_ctrl |= CTRL_SPEED_10;
+ break;
+ case IFM_100_TX:
+ sc->sc_ctrl |= CTRL_SPEED_100;
+ break;
+ case IFM_1000_T:
+ sc->sc_ctrl |= CTRL_SPEED_1000;
+ break;
+ default:
+ /*
+ * fiber?
+ * Shoud not enter here.
+ */
+ printf("unknown media (%x)\n", active);
+ break;
+ }
+ if (active & IFM_FDX)
+ sc->sc_ctrl |= CTRL_FD;
+ CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
}
+ } else if (sc->sc_type == WM_T_PCH) {
+ wm_k1_gig_workaround_hv(sc,
+ ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
+ }
- /* Work-around I218 hang issue */
- if ((sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM) ||
- (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V) ||
- (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM3) ||
- (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V3))
- wm_k1_workaround_lpt_lp(sc, link);
+ /*
+ * I217 Packet Loss issue:
+ * ensure that FEXTNVM4 Beacon Duration is set correctly
+ * on power up.
+ * Set the Beacon Duration for I217 to 8 usec
+ */
+ if (sc->sc_type >= WM_T_PCH_LPT) {
+ reg = CSR_READ(sc, WMREG_FEXTNVM4);
+ reg &= ~FEXTNVM4_BEACON_DURATION;
+ reg |= FEXTNVM4_BEACON_DURATION_8US;
+ CSR_WRITE(sc, WMREG_FEXTNVM4, reg);
+ }
- if (sc->sc_type >= WM_T_PCH_LPT) {
- /*
- * Set platform power management values for Latency
- * Tolerance Reporting (LTR)
- */
- wm_platform_pm_pch_lpt(sc,
- ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
- }
+ /* Work-around I218 hang issue */
+ if ((sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM) ||
+ (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V) ||
+ (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM3) ||
+ (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V3))
+ wm_k1_workaround_lpt_lp(sc, link);
- /* FEXTNVM6 K1-off workaround */
- if (sc->sc_type == WM_T_PCH_SPT) {
- reg = CSR_READ(sc, WMREG_FEXTNVM6);
- if (CSR_READ(sc, WMREG_PCIEANACFG)
- & FEXTNVM6_K1_OFF_ENABLE)
- reg |= FEXTNVM6_K1_OFF_ENABLE;
- else
- reg &= ~FEXTNVM6_K1_OFF_ENABLE;
- CSR_WRITE(sc, WMREG_FEXTNVM6, reg);
- }
+ if (sc->sc_type >= WM_T_PCH_LPT) {
+ /*
+ * Set platform power management values for Latency
+ * Tolerance Reporting (LTR)
+ */
+ wm_platform_pm_pch_lpt(sc,
+ ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
+ }
- if (!link)
- return;
+ /* FEXTNVM6 K1-off workaround */
+ if (sc->sc_type == WM_T_PCH_SPT) {
+ reg = CSR_READ(sc, WMREG_FEXTNVM6);
+ if (CSR_READ(sc, WMREG_PCIEANACFG)
+ & FEXTNVM6_K1_OFF_ENABLE)
+ reg |= FEXTNVM6_K1_OFF_ENABLE;
+ else
+ reg &= ~FEXTNVM6_K1_OFF_ENABLE;
+ CSR_WRITE(sc, WMREG_FEXTNVM6, reg);
+ }
- switch (sc->sc_type) {
- case WM_T_PCH2:
- wm_k1_workaround_lv(sc);
- /* FALLTHROUGH */
- case WM_T_PCH:
- if (sc->sc_phytype == WMPHY_82578)
- wm_link_stall_workaround_hv(sc);
- break;
- default:
- break;
- }
- } else if (icr & ICR_RXSEQ) {
- DPRINTF(WM_DEBUG_LINK, ("%s: LINK Receive sequence error\n",
- device_xname(sc->sc_dev)));
+ if (!link)
+ return;
+
+ switch (sc->sc_type) {
+ case WM_T_PCH2:
+ wm_k1_workaround_lv(sc);
+ /* FALLTHROUGH */
+ case WM_T_PCH:
+ if (sc->sc_phytype == WMPHY_82578)
+ wm_link_stall_workaround_hv(sc);
+ break;
+ default:
+ break;
}
}
@@ -8962,10 +9083,9 @@ wm_linkintr_tbi(struct wm_softc *sc, uin
}
/* Update LED */
wm_tbi_serdes_set_linkled(sc);
- } else if (icr & ICR_RXSEQ) {
+ } else if (icr & ICR_RXSEQ)
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n",
device_xname(sc->sc_dev)));
- }
}
/*
@@ -9038,10 +9158,9 @@ wm_linkintr_serdes(struct wm_softc *sc,
}
/* Update LED */
wm_tbi_serdes_set_linkled(sc);
- } else {
+ } else
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n",
device_xname(sc->sc_dev)));
- }
}
/*
@@ -9058,7 +9177,7 @@ wm_linkintr(struct wm_softc *sc, uint32_
if (sc->sc_flags & WM_F_HAS_MII)
wm_linkintr_gmii(sc, icr);
else if ((sc->sc_mediatype == WM_MEDIATYPE_SERDES)
- && (sc->sc_type >= WM_T_82575))
+ && ((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211)))
wm_linkintr_serdes(sc, icr);
else
wm_linkintr_tbi(sc, icr);
@@ -9083,10 +9202,9 @@ wm_intr_legacy(void *arg)
icr = CSR_READ(sc, WMREG_ICR);
if ((icr & sc->sc_icr) == 0)
break;
- if (handled == 0) {
+ if (handled == 0)
DPRINTF(WM_DEBUG_TX,
("%s: INTx: got intr\n",device_xname(sc->sc_dev)));
- }
if (rndval == 0)
rndval = icr;
@@ -9907,7 +10025,7 @@ wm_gmii_mediainit(struct wm_softc *sc, p
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);
@@ -10199,7 +10317,8 @@ wm_gmii_mdic_readreg(device_t dev, int p
uint32_t mdic = 0;
int i, rv;
- if (reg > MII_ADDRMASK) {
+ if ((sc->sc_phytype != WMPHY_82579) && (sc->sc_phytype != WMPHY_I217)
+ && (reg > MII_ADDRMASK)) {
device_printf(dev, "%s: PHYTYPE = %d, addr 0x%x > 0x1f\n",
__func__, sc->sc_phytype, reg);
reg &= MII_ADDRMASK;
@@ -10253,7 +10372,8 @@ wm_gmii_mdic_writereg(device_t dev, int
uint32_t mdic = 0;
int i;
- if (reg > MII_ADDRMASK) {
+ if ((sc->sc_phytype != WMPHY_82579) && (sc->sc_phytype != WMPHY_I217)
+ && (reg > MII_ADDRMASK)) {
device_printf(dev, "%s: PHYTYPE = %d, addr 0x%x > 0x1f\n",
__func__, sc->sc_phytype, reg);
reg &= MII_ADDRMASK;
@@ -10513,7 +10633,7 @@ wm_gmii_bm_readreg(device_t dev, int phy
|| (reg == 31)) ? 1 : phy;
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- wm_access_phy_wakeup_reg_bm(dev, reg, &val, 1);
+ wm_access_phy_wakeup_reg_bm(dev, reg, &val, true, false);
rv = val;
goto release;
}
@@ -10561,7 +10681,7 @@ wm_gmii_bm_writereg(device_t dev, int ph
uint16_t tmp;
tmp = val;
- wm_access_phy_wakeup_reg_bm(dev, reg, &tmp, 0);
+ wm_access_phy_wakeup_reg_bm(dev, reg, &tmp, false, false);
goto release;
}
@@ -10581,62 +10701,160 @@ release:
sc->phy.release(sc);
}
-static void
-wm_access_phy_wakeup_reg_bm(device_t dev, int offset, int16_t *val, int rd)
+/*
+ * wm_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
+ * @dev: pointer to the HW structure
+ * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
+ *
+ * Assumes semaphore already acquired and phy_reg points to a valid memory
+ * address to store contents of the BM_WUC_ENABLE_REG register.
+ */
+static int
+wm_enable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp)
{
- struct wm_softc *sc = device_private(dev);
- uint16_t regnum = BM_PHY_REG_NUM(offset);
- uint16_t wuce, reg;
+ uint16_t temp;
- DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
+ DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(dev), __func__));
- /* XXX Gig must be disabled for MDIO accesses to page 800 */
- if (sc->sc_type == WM_T_PCH) {
- /* XXX e1000 driver do nothing... why? */
- }
- /*
- * 1) Enable PHY wakeup register first.
- * See e1000_enable_phy_wakeup_reg_access_bm().
- */
+ if (!phy_regp)
+ return -1;
- /* Set page 769 */
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
+
+ /* Select Port Control Registers page */
wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
- BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
+ BM_PORT_CTRL_PAGE << IGP3_PAGE_SHIFT);
/* Read WUCE and save it */
- wuce = wm_gmii_mdic_readreg(dev, 1, BM_WUC_ENABLE_REG);
+ *phy_regp = wm_gmii_mdic_readreg(dev, 1, BM_WUC_ENABLE_REG);
+
+ /* Enable both PHY wakeup mode and Wakeup register page writes.
+ * Prevent a power state change by disabling ME and Host PHY wakeup.
+ */
+ temp = *phy_regp;
+ temp |= BM_WUC_ENABLE_BIT;
+ temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+ wm_gmii_mdic_writereg(dev, 1, BM_WUC_ENABLE_REG, temp);
+
+ /* Select Host Wakeup Registers page - caller now able to write
+ * registers on the Wakeup registers page
+ */
+ wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ BM_WUC_PAGE << IGP3_PAGE_SHIFT);
+
+ return 0;
+}
+
+/*
+ * wm_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ * @dev: pointer to the HW structure
+ * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ * Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ * Assumes semaphore already acquired and *phy_reg is the contents of the
+ * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ * caller.
+ */
+static int
+wm_disable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp)
+{
+
+ DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+ device_xname(dev), __func__));
- reg = wuce | BM_WUC_ENABLE_BIT;
- reg &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
- wm_gmii_mdic_writereg(dev, 1, BM_WUC_ENABLE_REG, reg);
+ if (!phy_regp)
+ return -1;
- /* Select page 800 */
+ /* Select Port Control Registers page */
wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
- BM_WUC_PAGE << BME1000_PAGE_SHIFT);
+ BM_PORT_CTRL_PAGE << IGP3_PAGE_SHIFT);
+
+ /* Restore 769.17 to its original value */
+ wm_gmii_mdic_writereg(dev, 1, BM_WUC_ENABLE_REG, *phy_regp);
+
+ return 0;
+}
+
+/*
+ * wm_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
+ * @sc: pointer to the HW structure
+ * @offset: register offset to be read or written
+ * @val: pointer to the data to read or write
+ * @rd: determines if operation is read or write
+ * @page_set: BM_WUC_PAGE already set and access enabled
+ *
+ * Read the PHY register at offset and store the retrieved information in
+ * data, or write data to PHY register at offset. Note the procedure to
+ * access the PHY wakeup registers is different than reading the other PHY
+ * registers. It works as such:
+ * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
+ * 2) Set page to 800 for host (801 if we were manageability)
+ * 3) Write the address using the address opcode (0x11)
+ * 4) Read or write the data using the data opcode (0x12)
+ * 5) Restore 769.17.2 to its original value
+ *
+ * Steps 1 and 2 are done by wm_enable_phy_wakeup_reg_access_bm() and
+ * step 5 is done by wm_disable_phy_wakeup_reg_access_bm().
+ *
+ * Assumes semaphore is already acquired. When page_set==TRUE, assumes
+ * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ * is responsible for calls to wm_[enable|disable]_phy_wakeup_reg_bm()).
+ */
+static int
+wm_access_phy_wakeup_reg_bm(device_t dev, int offset, int16_t *val, int rd,
+ bool page_set)
+{
+ struct wm_softc *sc = device_private(dev);
+ uint16_t regnum = BM_PHY_REG_NUM(offset);
+ uint16_t page = BM_PHY_REG_PAGE(offset);
+ uint16_t wuce;
+ int rv = 0;
+
+ DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
+ device_xname(dev), __func__));
+ /* XXX Gig must be disabled for MDIO accesses to page 800 */
+ if ((sc->sc_type == WM_T_PCH)
+ && ((CSR_READ(sc, WMREG_PHY_CTRL) & PHY_CTRL_GBE_DIS) == 0)) {
+ device_printf(dev,
+ "Attempting to access page %d while gig enabled.\n", page);
+ }
+
+ if (!page_set) {
+ /* Enable access to PHY wakeup registers */
+ rv = wm_enable_phy_wakeup_reg_access_bm(dev, &wuce);
+ if (rv != 0) {
+ device_printf(dev,
+ "%s: Could not enable PHY wakeup reg access\n",
+ __func__);
+ return rv;
+ }
+ }
+ DPRINTF(WM_DEBUG_GMII, ("%s: %s: Accessing PHY page %d reg 0x%x\n",
+ device_xname(sc->sc_dev), __func__, page, regnum));
/*
* 2) Access PHY wakeup register.
- * See e1000_access_phy_wakeup_reg_bm.
+ * See wm_access_phy_wakeup_reg_bm.
*/
- /* Write page 800 */
+ /* Write the Wakeup register page offset value using opcode 0x11 */
wm_gmii_mdic_writereg(dev, 1, BM_WUC_ADDRESS_OPCODE, regnum);
- if (rd)
+ if (rd) {
+ /* Read the Wakeup register page value using opcode 0x12 */
*val = wm_gmii_mdic_readreg(dev, 1, BM_WUC_DATA_OPCODE);
- else
+ } else {
+ /* Write the Wakeup register page value using opcode 0x12 */
wm_gmii_mdic_writereg(dev, 1, BM_WUC_DATA_OPCODE, *val);
+ }
- /*
- * 3) Disable PHY wakeup register.
- * See e1000_disable_phy_wakeup_reg_access_bm().
- */
- /* Set page 769 */
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
- BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT);
+ if (!page_set)
+ rv = wm_disable_phy_wakeup_reg_access_bm(dev, &wuce);
- wm_gmii_mdic_writereg(dev, 1, BM_WUC_ENABLE_REG, wuce);
+ return rv;
}
/*
@@ -10673,10 +10891,8 @@ wm_gmii_hv_readreg_locked(device_t dev,
phy = (page >= HV_INTC_FC_PAGE_START) ? 1 : phy;
/* Page 800 works differently than the rest so it has its own func */
- if (page == BM_WUC_PAGE) {
- wm_access_phy_wakeup_reg_bm(dev, reg, val, 1);
- return 0;
- }
+ if (page == BM_WUC_PAGE)
+ return wm_access_phy_wakeup_reg_bm(dev, reg, val, true, false);
/*
* Lower than page 768 works differently than the rest so it has its
@@ -10733,6 +10949,7 @@ wm_gmii_hv_writereg_locked(device_t dev,
struct wm_softc *sc = device_private(dev);
uint16_t page = BM_PHY_REG_PAGE(reg);
uint16_t regnum = BM_PHY_REG_NUM(reg);
+ int rv;
phy = (page >= HV_INTC_FC_PAGE_START) ? 1 : phy;
@@ -10741,8 +10958,8 @@ wm_gmii_hv_writereg_locked(device_t dev,
uint16_t tmp;
tmp = val;
- wm_access_phy_wakeup_reg_bm(dev, reg, &tmp, 0);
- return 0;
+ rv = wm_access_phy_wakeup_reg_bm(dev, reg, &tmp, false, false);
+ return rv;
}
/*
@@ -11220,7 +11437,7 @@ wm_tbi_mediainit(struct wm_softc *sc)
sc->sc_mii.mii_ifp = ifp;
sc->sc_ethercom.ec_mii = &sc->sc_mii;
- if ((sc->sc_type >= WM_T_82575)
+ if (((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211))
&& (sc->sc_mediatype == WM_MEDIATYPE_SERDES))
ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK,
wm_serdes_mediachange, wm_serdes_mediastatus);
@@ -11495,14 +11712,13 @@ wm_check_for_link(struct wm_softc *sc)
__func__));
CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
CSR_WRITE(sc, WMREG_CTRL, (ctrl & ~CTRL_SLU));
- } else if (signal && ((rxcw & RXCW_C) != 0)) {
+ } else if (signal && ((rxcw & RXCW_C) != 0))
DPRINTF(WM_DEBUG_LINK, ("%s: %s: /C/",
device_xname(sc->sc_dev), __func__));
- } else {
+ else
DPRINTF(WM_DEBUG_LINK, ("%s: %s: linkup %08x,%08x,%08x\n",
device_xname(sc->sc_dev), __func__, rxcw, ctrl,
status));
- }
return 0;
}
@@ -12882,12 +13098,11 @@ wm_nvm_validate_checksum(struct wm_softc
|| (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) {
/* XXX PCH_SPT? */
wm_nvm_read(sc, csum_wordaddr, 1, &eeprom_data);
- if ((eeprom_data & valid_checksum) == 0) {
+ if ((eeprom_data & valid_checksum) == 0)
DPRINTF(WM_DEBUG_NVM,
("%s: NVM need to be updated (%04x != %04x)\n",
device_xname(sc->sc_dev), eeprom_data,
valid_checksum));
- }
}
if ((wm_debug & WM_DEBUG_NVM) != 0) {
@@ -13839,8 +14054,8 @@ wm_gate_hw_phy_config_ich8lan(struct wm_
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 +14070,17 @@ wm_smbustopci(struct wm_softc *sc)
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 +14089,9 @@ wm_smbustopci(struct wm_softc *sc)
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 +14099,10 @@ wm_smbustopci(struct wm_softc *sc)
/* 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 +14119,16 @@ wm_smbustopci(struct wm_softc *sc)
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 +14146,38 @@ wm_smbustopci(struct wm_softc *sc)
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 +14316,12 @@ wm_ulp_disable(struct wm_softc *sc)
}
/* 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__));
+ return -1;
+ }
/* Toggle LANPHYPC */
wm_toggle_lanphypc_pch_lpt(sc);
@@ -14131,26 +14386,87 @@ release:
}
/* WOL in the newer chipset interfaces (pchlan) */
-static void
+static int
wm_enable_phy_wakeup(struct wm_softc *sc)
{
-#if 0
- uint16_t preg;
+ device_t dev = sc->sc_dev;
+ uint32_t mreg, moff;
+ uint16_t wuce, wuc, wufc, preg;
+ int i, rv;
+
+ KASSERT(sc->sc_type >= WM_T_PCH);
/* Copy MAC RARs to PHY RARs */
+ wm_copy_rx_addrs_to_phy_ich8lan(sc);
+
+ /* Activate PHY wakeup */
+ rv = sc->phy.acquire(sc);
+ if (rv != 0) {
+ device_printf(dev, "%s: failed to acquire semaphore\n",
+ __func__);
+ return rv;
+ }
+
+ /*
+ * Enable access to PHY wakeup registers.
+ * BM_MTA, BM_RCTL, BM_WUFC and BM_WUC are in BM_WUC_PAGE.
+ */
+ rv = wm_enable_phy_wakeup_reg_access_bm(dev, &wuce);
+ if (rv != 0) {
+ device_printf(dev,
+ "%s: Could not enable PHY wakeup reg access\n", __func__);
+ goto release;
+ }
/* Copy MAC MTA to PHY MTA */
+ for (i = 0; i < WM_ICH8_MC_TABSIZE; i++) {
+ uint16_t lo, hi;
+
+ mreg = CSR_READ(sc, WMREG_CORDOVA_MTA + (i * 4));
+ lo = (uint16_t)(mreg & 0xffff);
+ hi = (uint16_t)((mreg >> 16) & 0xffff);
+ wm_access_phy_wakeup_reg_bm(dev, BM_MTA(i), &lo, 0, true);
+ wm_access_phy_wakeup_reg_bm(dev, BM_MTA(i) + 1, &hi, 0, true);
+ }
/* Configure PHY Rx Control register */
+ wm_access_phy_wakeup_reg_bm(dev, BM_RCTL, &preg, 1, true);
+ mreg = CSR_READ(sc, WMREG_RCTL);
+ if (mreg & RCTL_UPE)
+ preg |= BM_RCTL_UPE;
+ if (mreg & RCTL_MPE)
+ preg |= BM_RCTL_MPE;
+ preg &= ~(BM_RCTL_MO_MASK);
+ moff = __SHIFTOUT(mreg, RCTL_MO);
+ if (moff != 0)
+ preg |= moff << BM_RCTL_MO_SHIFT;
+ if (mreg & RCTL_BAM)
+ preg |= BM_RCTL_BAM;
+ if (mreg & RCTL_PMCF)
+ preg |= BM_RCTL_PMCF;
+ mreg = CSR_READ(sc, WMREG_CTRL);
+ if (mreg & CTRL_RFCE)
+ preg |= BM_RCTL_RFCE;
+ wm_access_phy_wakeup_reg_bm(dev, BM_RCTL, &preg, 0, true);
+ wuc = WUC_APME | WUC_PME_EN;
+ wufc = WUFC_MAG;
/* Enable PHY wakeup in MAC register */
+ CSR_WRITE(sc, WMREG_WUC,
+ WUC_PHY_WAKE | WUC_PME_STATUS | WUC_APMPME | wuc);
+ CSR_WRITE(sc, WMREG_WUFC, wufc);
/* Configure and enable PHY wakeup in PHY registers */
+ wm_access_phy_wakeup_reg_bm(dev, BM_WUC, &wuc, 0, true);
+ wm_access_phy_wakeup_reg_bm(dev, BM_WUFC, &wufc, 0, true);
- /* Activate PHY wakeup */
+ wuce |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
+ wm_disable_phy_wakeup_reg_access_bm(dev, &wuce);
- /* XXX */
-#endif
+release:
+ sc->phy.release(sc);
+
+ return 0;
}
/* Power down workaround on D3 */
@@ -14191,7 +14507,7 @@ wm_igp3_phy_powerdown_workaround_ich8lan
}
/*
- * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
+ * wm_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
* @sc: pointer to the HW structure
*
* During S0 to Sx transition, it is possible the link remains at gig
@@ -14269,23 +14585,94 @@ out:
}
}
+/*
+ * wm_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ * @sc: pointer to the HW structure
+ *
+ * During Sx to S0 transitions on non-managed devices or managed devices
+ * on which PHY resets are not blocked, if the PHY registers cannot be
+ * accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ * the PHY.
+ * On i217, setup Intel Rapid Start Technology.
+ */
+static int
+wm_resume_workarounds_pchlan(struct wm_softc *sc)
+{
+ device_t dev = sc->sc_dev;
+ int rv;
+
+ if (sc->sc_type < WM_T_PCH2)
+ return 0;
+
+ rv = wm_init_phy_workarounds_pchlan(sc);
+ if (rv != 0)
+ return -1;
+
+ /* For i217 Intel Rapid Start Technology support when the system
+ * is transitioning from Sx and no manageability engine is present
+ * configure SMBus to restore on reset, disable proxy, and enable
+ * the reset on MTA (Multicast table array).
+ */
+ if (sc->sc_phytype == WMPHY_I217) {
+ uint16_t phy_reg;
+
+ if (sc->phy.acquire(sc) != 0)
+ return -1;
+
+ /* Clear Auto Enable LPI after link up */
+ sc->phy.readreg_locked(dev, 1, I217_LPI_GPIO_CTRL, &phy_reg);
+ phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
+ sc->phy.writereg_locked(dev, 1, I217_LPI_GPIO_CTRL, phy_reg);
+
+ if ((CSR_READ(sc, WMREG_FWSM) & FWSM_FW_VALID) == 0) {
+ /* Restore clear on SMB if no manageability engine
+ * is present
+ */
+ rv = sc->phy.readreg_locked(dev, 1, I217_MEMPWR,
+ &phy_reg);
+ if (rv != 0)
+ goto release;
+ phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE;
+ sc->phy.writereg_locked(dev, 1, I217_MEMPWR, phy_reg);
+
+ /* Disable Proxy */
+ sc->phy.writereg_locked(dev, 1, I217_PROXY_CTRL, 0);
+ }
+ /* Enable reset on MTA */
+ sc->phy.readreg_locked(dev, 1, I217_CFGREG, &phy_reg);
+ if (rv != 0)
+ goto release;
+ phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET;
+ sc->phy.writereg_locked(dev, 1, I217_CFGREG, phy_reg);
+
+release:
+ sc->phy.release(sc);
+ return rv;
+ }
+
+ return 0;
+}
+
static void
wm_enable_wakeup(struct wm_softc *sc)
{
uint32_t reg, pmreg;
pcireg_t pmode;
+ int rv = 0;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT,
- &pmreg, NULL) == 0)
+ &pmreg, NULL) == 0)
return;
+ if ((sc->sc_flags & WM_F_WOL) == 0)
+ goto pme;
+
/* Advertise the wakeup capability */
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_SWDPIN(2)
| CTRL_SWDPIN(3));
- CSR_WRITE(sc, WMREG_WUC, WUC_APME);
/* Keep the laser running on fiber adapters */
if ((sc->sc_mediatype == WM_MEDIATYPE_FIBER)
@@ -14296,21 +14683,25 @@ wm_enable_wakeup(struct wm_softc *sc)
}
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) ||
- (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH))
+ (sc->sc_type == WM_T_ICH10) || (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_suspend_workarounds_ich8lan(sc);
- reg = CSR_READ(sc, WMREG_WUFC) | WUFC_MAG;
#if 0 /* for the multicast packet */
+ reg = CSR_READ(sc, WMREG_WUFC) | WUFC_MAG;
reg |= WUFC_MC;
CSR_WRITE(sc, WMREG_RCTL, CSR_READ(sc, WMREG_RCTL) | RCTL_MPE);
#endif
- if (sc->sc_type >= WM_T_PCH)
- wm_enable_phy_wakeup(sc);
- else {
+ if (sc->sc_type >= WM_T_PCH) {
+ rv = wm_enable_phy_wakeup(sc);
+ if (rv != 0)
+ goto pme;
+ } else {
/* Enable wakeup by the MAC */
- CSR_WRITE(sc, WMREG_WUC, CSR_READ(sc, WMREG_WUC) | WUC_PME_EN);
- CSR_WRITE(sc, WMREG_WUFC, reg);
+ CSR_WRITE(sc, WMREG_WUC, WUC_PME_EN);
+ CSR_WRITE(sc, WMREG_WUFC, WUFC_MAG);
}
if (((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
@@ -14319,15 +14710,16 @@ wm_enable_wakeup(struct wm_softc *sc)
&& (sc->sc_phytype == WMPHY_IGP_3))
wm_igp3_phy_powerdown_workaround_ich8lan(sc);
+pme:
/* Request PME */
pmode = pci_conf_read(sc->sc_pc, sc->sc_pcitag, pmreg + PCI_PMCSR);
-#if 0
- /* Disable WOL */
- pmode &= ~(PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN);
-#else
- /* For WOL */
- pmode |= PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN;
-#endif
+ if ((rv == 0) && (sc->sc_flags & WM_F_WOL) != 0) {
+ /* For WOL */
+ pmode |= PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN;
+ } else {
+ /* Disable WOL */
+ pmode &= ~(PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN);
+ }
pci_conf_write(sc->sc_pc, sc->sc_pcitag, pmreg + PCI_PMCSR, pmode);
}
@@ -14500,7 +14892,6 @@ wm_kmrn_lock_loss_workaround_ich8lan(str
if (__SHIFTOUT(status, STATUS_SPEED) != STATUS_SPEED_1000)
return;
- reg = CSR_READ(sc, WMREG_PHY_CTRL);
for (i = 0; i < 10; i++) {
/* read twice */
reg = mii->mii_readreg(sc->sc_dev, 1, IGP3_KMRN_DIAG);
@@ -14560,7 +14951,7 @@ wm_gig_downshift_workaround_ich8lan(stru
* XXX should be moved to new PHY driver?
*/
static void
-wm_hv_phy_workaround_ich8lan(struct wm_softc *sc)
+wm_hv_phy_workarounds_ich8lan(struct wm_softc *sc)
{
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
@@ -14604,11 +14995,54 @@ wm_hv_phy_workaround_ich8lan(struct wm_s
}
/*
+ * wm_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
+ * @sc: pointer to the HW structure
+ */
+static void
+wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *sc)
+{
+ device_t dev = sc->sc_dev;
+ uint32_t mac_reg;
+ uint16_t i, wuce;
+ int count;
+
+ DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+ device_xname(sc->sc_dev), __func__));
+
+ if (sc->phy.acquire(sc) != 0)
+ return;
+ if (wm_enable_phy_wakeup_reg_access_bm(dev, &wuce) != 0)
+ goto release;
+
+ /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */
+ count = wm_rar_count(sc);
+ for (i = 0; i < count; i++) {
+ uint16_t lo, hi;
+ mac_reg = CSR_READ(sc, WMREG_CORDOVA_RAL(i));
+ lo = (uint16_t)(mac_reg & 0xffff);
+ hi = (uint16_t)((mac_reg >> 16) & 0xffff);
+ wm_access_phy_wakeup_reg_bm(dev, BM_RAR_L(i), &lo, 0, true);
+ wm_access_phy_wakeup_reg_bm(dev, BM_RAR_M(i), &hi, 0, true);
+
+ mac_reg = CSR_READ(sc, WMREG_CORDOVA_RAH(i));
+ lo = (uint16_t)(mac_reg & 0xffff);
+ hi = (uint16_t)((mac_reg & RAL_AV) >> 16);
+ wm_access_phy_wakeup_reg_bm(dev, BM_RAR_H(i), &lo, 0, true);
+ wm_access_phy_wakeup_reg_bm(dev, BM_RAR_CTRL(i), &hi, 0, true);
+ }
+
+ wm_disable_phy_wakeup_reg_access_bm(dev, &wuce);
+
+release:
+ sc->phy.release(sc);
+}
+
+/*
* wm_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
* done after every PHY reset.
*/
static void
-wm_lv_phy_workaround_ich8lan(struct wm_softc *sc)
+wm_lv_phy_workarounds_ich8lan(struct wm_softc *sc)
{
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
@@ -14623,7 +15057,7 @@ wm_lv_phy_workaround_ich8lan(struct wm_s
}
/**
- * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
+ * wm_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
* @link: link up bool flag
*
* When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
@@ -15166,6 +15600,11 @@ wm_pll_workaround_i210(struct wm_softc *
bool wa_done = false;
int i;
+ /* Get Power Management cap offset */
+ if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT,
+ &pmreg, NULL) == 0)
+ return;
+
/* Save WUC and MDICNFG registers */
wuc = CSR_READ(sc, WMREG_WUC);
mdicnfg = CSR_READ(sc, WMREG_MDICNFG);
@@ -15177,10 +15616,6 @@ wm_pll_workaround_i210(struct wm_softc *
nvmword = INVM_DEFAULT_AL;
tmp_nvmword = nvmword | INVM_PLL_WO_VAL;
- /* Get Power Management cap offset */
- if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT,
- &pmreg, NULL) == 0)
- return;
for (i = 0; i < WM_MAX_PLL_TRIES; i++) {
phyval = wm_gmii_gs40g_readreg(sc->sc_dev, 1,
GS40G_PHY_PLL_FREQ_PAGE | GS40G_PHY_PLL_FREQ_REG);
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.98.6.6 src/sys/dev/pci/if_wmreg.h:1.98.6.7
--- src/sys/dev/pci/if_wmreg.h:1.98.6.6 Tue Dec 4 11:21:32 2018
+++ src/sys/dev/pci/if_wmreg.h Thu Jan 31 06:43:48 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.98.6.6 2018/12/04 11:21:32 martin Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.98.6.7 2019/01/31 06:43:48 martin Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -773,7 +773,7 @@ struct livengood_tcpip_ctxdesc {
#define RCTL_DTYP_ONEBUF RCTL_DTYP(0) /* use one buffer(not split header). */
#define RCTL_DTYP_SPH RCTL_DTYP(1) /* split header buffer. */
/* RCTL_DTYP(2) and RCTL_DTYP(3) are reserved. */
-#define RCTL_MO(x) ((x) << 12) /* multicast offset */
+#define RCTL_MO __BITS(13, 12) /* multicast offset */
#define RCTL_BAM (1U << 15) /* broadcast accept mode */
#define RCTL_RDMTS_HEX __BIT(16)
#define RCTL_2k (0 << 16) /* 2k Rx buffers */
@@ -1195,15 +1195,38 @@ struct livengood_tcpip_ctxdesc {
#define WMREG_WUC 0x5800 /* Wakeup Control */
#define WUC_APME 0x00000001 /* APM Enable */
#define WUC_PME_EN 0x00000002 /* PME Enable */
+#define WUC_PME_STATUS 0x00000004 /* PME Status */
+#define WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
+#define WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
#define WMREG_WUFC 0x5808 /* Wakeup Filter Control */
-#define WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
-#define WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
-#define WUFC_MC 0x00000008 /* Directed Multicast Wakeup En */
-#define WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
-#define WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup En */
-#define WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup En */
-#define WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup En */
+#define WUFC_LNKC __BIT(0) /* Link Status Change Wakeup Enable */
+#define WUFC_MAG __BIT(1) /* Magic Packet Wakeup Enable */
+#define WUFC_EX __BIT(2) /* Directed Exact Wakeup Enable */
+#define WUFC_MC __BIT(3) /* Directed Multicast Wakeup En */
+#define WUFC_BC __BIT(4) /* Broadcast Wakeup Enable */
+#define WUFC_ARPDIR __BIT(5) /* ARP Request Packet Wakeup En */
+#define WUFC_IPV4 __BIT(6) /* Directed IPv4 Packet Wakeup En */
+#define WUFC_IPV6 __BIT(7) /* Directed IPv6 Packet Wakeup En */
+#define WUFC_NS __BIT(9) /* NS Wakeup En */
+#define WUFC_NSDIR __BIT(10) /* NS Directed En */
+#define WUFC_ARP __BIT(11) /* ARP request En */
+#define WUFC_FLEX_HQ __BIT(14) /* Flex Filters Host Queueing En */
+#define WUFC_NOTCO __BIT(15) /* ? */
+#define WUFC_FLX __BITS(23, 16) /* Flexible Filter [0-7] En */
+#define WUFC_FLXACT __BITS(27, 24) /* Flexible Filter [0-3] Action */
+#define WUFC_FW_RST_WK __BIT(31) /* Wake on Firmware Reset Assert En */
+
+#define WMREG_WUS 0x5810 /* Wakeup Status (R/W1C) */
+ /* Bit 30-24 and 15-12 are reserved */
+#define WUS_MNG __BIT(8) /* Manageability event */
+#define WUS_FLAGS "\20" \
+ "\1LINKC" "\2MAG" "\3EX" "\4MC" \
+ "\5BC" "\6ARPDIR" "\7IPV4" "\10IPV6" \
+ "\11MNG" "\12NS" "\13NSDIR" "\14ARP" \
+ "\21FLX0" "\22FLX1" "\23FLX2" "\24FLX3" \
+ "\25FLX4" "\26FLX5" "\27FLX6" "\30FLX7" \
+ "\40FW_RST_WK"
#define WMREG_MRQC 0x5818 /* Multiple Receive Queues Command */
#define MRQC_DISABLE_RSS 0x00000000
Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.33.6.3 src/sys/dev/pci/if_wmvar.h:1.33.6.4
--- src/sys/dev/pci/if_wmvar.h:1.33.6.3 Sat Aug 11 14:47:32 2018
+++ src/sys/dev/pci/if_wmvar.h Thu Jan 31 06:43:48 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmvar.h,v 1.33.6.3 2018/08/11 14:47:32 martin Exp $ */
+/* $NetBSD: if_wmvar.h,v 1.33.6.4 2019/01/31 06:43:48 martin Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -105,7 +105,7 @@
"\15" "PCIX" "\16" "CSA" "\17" "PCIE" "\20" "SGMII" \
"\21" "NEWQUEUE" "\22" "ASF_FIRM" "\23" "ARC_SUBSYS" "\24" "AMT" \
"\25" "MANAGE" "\26" "WOL" "\27" "EEE" "\30" "ATTACHED" \
- "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\40" "CLSEMWA"
+ "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\34" "CLSEMWA"
/*
* Variations of Intel gigabit Ethernet controller:
@@ -166,17 +166,17 @@ typedef enum {
WMPHY_M88,
WMPHY_IGP,
WMPHY_IGP_2,
- WMPHY_GG82563,
- WMPHY_IGP_3,
- WMPHY_IFE,
- WMPHY_BM,
- WMPHY_82577,
- WMPHY_82578,
- WMPHY_82579,
- WMPHY_I217,
- WMPHY_82580,
+ WMPHY_GG82563, /* 82563: 80003 */
+ WMPHY_IGP_3, /* 82566: 82575, 82576, ICH8, ICH9 */
+ WMPHY_IFE, /* 82562 */
+ WMPHY_BM, /* 82567: ICH8 ICH9 ICH10 */
+ WMPHY_82577, /* 82577: PCH */
+ WMPHY_82578, /* 82578: PCH */
+ WMPHY_82579, /* 82579: PCH2 */
+ WMPHY_I217, /* I217: _LPT, I218: _LPT, I219: _SPT _CNP */
+ WMPHY_82580, /* 82580: 82580 or I350 */
WMPHY_VF,
- WMPHY_I210
+ WMPHY_I210 /* I210: I210 I211 */
} wm_phy_type;