Source-Changes-HG archive

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

[src/trunk]: src/sys/dev - Don't setup WoL on non-WoL capable port.



details:   https://anonhg.NetBSD.org/src/rev/269dc8989e52
branches:  trunk
changeset: 446808:269dc8989e52
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Dec 20 09:32:12 2018 +0000

description:
- Don't setup WoL on non-WoL capable port.
- Setup PHY wakeup feature on PCH and newer. Tested on Thinkpad X220.

diffstat:

 sys/dev/mii/inbmphyreg.h |   21 ++-
 sys/dev/pci/if_wm.c      |  426 ++++++++++++++++++++++++++++++++++++----------
 sys/dev/pci/if_wmreg.h   |    4 +-
 sys/dev/pci/if_wmvar.h   |    6 +-
 4 files changed, 358 insertions(+), 99 deletions(-)

diffs (truncated from 705 to 300 lines):

diff -r d57f9872fa6c -r 269dc8989e52 sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h  Thu Dec 20 09:17:04 2018 +0000
+++ b/sys/dev/mii/inbmphyreg.h  Thu Dec 20 09:32:12 2018 +0000
@@ -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 @@
 #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 @@
 #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_ */
diff -r d57f9872fa6c -r 269dc8989e52 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Dec 20 09:17:04 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Dec 20 09:32:12 2018 +0000
@@ -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 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 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_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_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 @@
 }
 
 /*
+ *
+ *
+ */
+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 @@
         * 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 @@
         */
        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 @@
        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 @@
        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 @@
                    || (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 @@
                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 @@
        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)
+{
+       uint16_t temp;
+
+       DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+               device_xname(dev), __func__));
+
+       if (!phy_regp)
+               return -1;
+
+       /* 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_PORT_CTRL_PAGE << IGP3_PAGE_SHIFT);
+
+       /* Read WUCE and save it */
+       *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__));
+
+       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);



Home | Main Index | Thread Index | Old Index