Module Name:    src
Committed By:   msaitoh
Date:           Fri Dec 14 09:47:40 UTC 2018

Modified Files:
        src/sys/dev/pci: if_wm.c if_wmreg.h

Log Message:
- 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.


To generate a diff of this commit:
cvs rdiff -u -r1.603 -r1.604 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.109 -r1.110 src/sys/dev/pci/if_wmreg.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/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.603 src/sys/dev/pci/if_wm.c:1.604
--- src/sys/dev/pci/if_wm.c:1.603	Wed Dec 12 08:49:33 2018
+++ src/sys/dev/pci/if_wm.c	Fri Dec 14 09:47:40 2018
@@ -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 @@ 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);
+		break;
+	default:
+		break;
+	}
 	/* Reset the chip to a known state. */
 	wm_reset(sc);
 
@@ -2480,16 +2496,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:
@@ -2498,9 +2520,12 @@ 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;
 	}
 
@@ -2508,6 +2533,42 @@ alloc_retry:
 	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 @@ wm_resume(device_t self, const pmf_qual_
 {
 	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);

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.109 src/sys/dev/pci/if_wmreg.h:1.110
--- src/sys/dev/pci/if_wmreg.h:1.109	Mon Nov 19 06:38:58 2018
+++ src/sys/dev/pci/if_wmreg.h	Fri Dec 14 09:47:40 2018
@@ -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 @@ 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

Reply via email to