Module Name: src
Committed By: msaitoh
Date: Thu Dec 20 09:32:13 UTC 2018
Modified Files:
src/sys/dev/mii: inbmphyreg.h
src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h
Log Message:
- Don't setup WoL on non-WoL capable port.
- Setup PHY wakeup feature on PCH and newer. Tested on Thinkpad X220.
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/mii/inbmphyreg.h
cvs rdiff -u -r1.609 -r1.610 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.110 -r1.111 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.40 -r1.41 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.14 src/sys/dev/mii/inbmphyreg.h:1.15
--- src/sys/dev/mii/inbmphyreg.h:1.14 Thu Dec 13 05:22:44 2018
+++ src/sys/dev/mii/inbmphyreg.h Thu Dec 20 09:32:12 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: inbmphyreg.h,v 1.14 2018/12/13 05:22:44 msaitoh Exp $ */
+/* $NetBSD: inbmphyreg.h,v 1.15 2018/12/20 09:32:12 msaitoh Exp $ */
/*******************************************************************************
Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
@@ -160,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
@@ -169,6 +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.609 src/sys/dev/pci/if_wm.c:1.610
--- src/sys/dev/pci/if_wm.c:1.609 Thu Dec 20 08:59:22 2018
+++ src/sys/dev/pci/if_wm.c Thu Dec 20 09:32:13 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.609 2018/12/20 08:59:22 msaitoh Exp $ */
+/* $NetBSD: if_wm.c,v 1.610 2018/12/20 09:32:13 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.609 2018/12/20 08:59:22 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.610 2018/12/20 09:32:13 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -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 *);
@@ -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);
@@ -954,7 +958,7 @@ static void wm_init_manageability(struct
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 *);
@@ -972,6 +976,7 @@ 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_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);
@@ -3566,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.
@@ -3602,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)
@@ -6050,7 +6082,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.
@@ -10288,7 +10320,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;
@@ -10342,7 +10375,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;
@@ -10602,7 +10636,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;
}
@@ -10650,7 +10684,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;
}
@@ -10670,39 +10704,139 @@ 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;
+
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
- /* Set page 769 */
+ /* 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);
- 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);
+ /* 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);
- /* Select page 800 */
+ 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 << BME1000_PAGE_SHIFT);
+ 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__));
+
+ if (!phy_regp)
+ return -1;
+
+ /* Select Port Control Registers page */
+ wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ 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.
@@ -10720,15 +10854,10 @@ wm_access_phy_wakeup_reg_bm(device_t dev
wm_gmii_mdic_writereg(dev, 1, BM_WUC_DATA_OPCODE, *val);
}
- /*
- * 3) Disable PHY wakeup register.
- * See wm_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;
}
/*
@@ -10765,10 +10894,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
@@ -10825,6 +10952,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;
@@ -10833,8 +10961,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;
}
/*
@@ -14263,26 +14391,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 */
@@ -14473,18 +14662,21 @@ 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)
@@ -14495,21 +14687,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)
@@ -14518,15 +14714,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);
}
@@ -14803,6 +15000,49 @@ wm_hv_phy_workarounds_ich8lan(struct wm_
}
/*
+ * 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.
*/
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.110 src/sys/dev/pci/if_wmreg.h:1.111
--- src/sys/dev/pci/if_wmreg.h:1.110 Fri Dec 14 09:47:40 2018
+++ src/sys/dev/pci/if_wmreg.h Thu Dec 20 09:32:13 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.110 2018/12/14 09:47:40 msaitoh Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.111 2018/12/20 09:32:13 msaitoh 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 */
Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.40 src/sys/dev/pci/if_wmvar.h:1.41
--- src/sys/dev/pci/if_wmvar.h:1.40 Fri Dec 14 06:28:09 2018
+++ src/sys/dev/pci/if_wmvar.h Thu Dec 20 09:32:13 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmvar.h,v 1.40 2018/12/14 06:28:09 msaitoh Exp $ */
+/* $NetBSD: if_wmvar.h,v 1.41 2018/12/20 09:32:13 msaitoh Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -172,8 +172,8 @@ typedef enum {
WMPHY_BM,
WMPHY_82577,
WMPHY_82578,
- WMPHY_82579,
- WMPHY_I217,
+ WMPHY_82579, /* with PCH2 */
+ WMPHY_I217, /* with PCH_LPT, PCH_SPT, PCH_CNP */
WMPHY_82580,
WMPHY_VF,
WMPHY_I210