Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci - Fix availability detection of WoL on some chip...



details:   https://anonhg.NetBSD.org/src/rev/0a48adf163cd
branches:  trunk
changeset: 446676:0a48adf163cd
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Fri Dec 14 09:47:40 2018 +0000

description:
- Fix availability detection of WoL on some chips. This change has no effect
other than dmesg because WM_F_WOL is currently not used to change the behavior:
  - For ICH/PCH, check the capability not from NVM but from the WUC register.
    Check the value before clearing the register.
  - 82580 and newer have per-port NVM block, so read the area correctly.
    Note that 82580, I350 and I354 may have PCI function 2 and 3.
  - Some devices can't detect WoL capability neither from NVM nor from WUC.
    Use PCI device ID and the function number.
- Print the WUS (WakeUp Status) register bits when resume.

diffstat:

 sys/dev/pci/if_wm.c    |  84 ++++++++++++++++++++++++++++++++++++++++++++-----
 sys/dev/pci/if_wmreg.h |  39 ++++++++++++++++++----
 2 files changed, 106 insertions(+), 17 deletions(-)

diffs (194 lines):

diff -r c066f12890a8 -r 0a48adf163cd sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Fri Dec 14 09:21:32 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Fri Dec 14 09:47:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.603 2018/12/12 08:49:33 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.604 2018/12/14 09:47:40 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.603 2018/12/12 08:49:33 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.604 2018/12/14 09:47:40 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -2379,6 +2379,22 @@
         */
        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);
+               break;
+       default:
+               break;
+       }
        /* Reset the chip to a known state. */
        wm_reset(sc);
 
@@ -2480,16 +2496,22 @@
        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:
@@ -2498,9 +2520,12 @@
        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;
        }
 
@@ -2508,6 +2533,42 @@
        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) {
@@ -2977,6 +3038,11 @@
 {
        struct wm_softc *sc = device_private(self);
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       char buf[256];
+
+       snprintb(buf, sizeof(buf), WUS_FLAGS, CSR_READ(sc, WMREG_WUS));
+       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);
diff -r c066f12890a8 -r 0a48adf163cd sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h    Fri Dec 14 09:21:32 2018 +0000
+++ b/sys/dev/pci/if_wmreg.h    Fri Dec 14 09:47:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wmreg.h,v 1.109 2018/11/19 06:38:58 msaitoh Exp $   */
+/*     $NetBSD: if_wmreg.h,v 1.110 2018/12/14 09:47:40 msaitoh Exp $   */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -1195,15 +1195,38 @@
 #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



Home | Main Index | Thread Index | Old Index