Module Name:    src
Committed By:   msaitoh
Date:           Thu Nov 22 15:09:46 UTC 2018

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

Log Message:
- Add wm_k1_workaround_lv() from FreeBSD. It's PCH2 specifc:
    Workaround to set the K1 beacon duration for 82579 parts in 10Mbps.
    Disable K1 for 1000 and 100 speeds.
- Make wm_link_stall_workaround_hv() and move an 82578 specific code into it.
  Don't apply the workaround if BMCR_LOOP bit is set. Same as FreeBSD.
- Add comment. Modify comment.


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/mii/inbmphyreg.h
cvs rdiff -u -r1.600 -r1.601 src/sys/dev/pci/if_wm.c

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.11 src/sys/dev/mii/inbmphyreg.h:1.12
--- src/sys/dev/mii/inbmphyreg.h:1.11	Fri Nov  2 03:22:19 2018
+++ src/sys/dev/mii/inbmphyreg.h	Thu Nov 22 15:09:45 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: inbmphyreg.h,v 1.11 2018/11/02 03:22:19 msaitoh Exp $	*/
+/*	$NetBSD: inbmphyreg.h,v 1.12 2018/11/22 15:09:45 msaitoh Exp $	*/
 /*******************************************************************************
 Copyright (c) 2001-2005, Intel Corporation 
 All rights reserved.
@@ -74,6 +74,13 @@ POSSIBILITY OF SUCH DAMAGE.
 #define BME1000_PSCR_DOWNSHIFT_COUNTER_MASK     0x7000
 #define BME1000_PSCR_DOWNSHIFT_COUNTER_SHIFT    12
 
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS		BME1000_REG(0, 17)
+#define BM_CS_STATUS_LINK_UP	0x0400
+#define BM_CS_STATUS_RESOLVED	0x0800
+#define BM_CS_STATUS_SPEED_MASK	0xC000
+#define BM_CS_STATUS_SPEED_1000	0x8000
+
 #define BME1000_PHY_PAGE_SELECT	BME1000_REG(0, 22) /* Page Select */
 
 #define BME1000_BIAS_SETTING	29
@@ -91,6 +98,14 @@ POSSIBILITY OF SUCH DAMAGE.
 #define HV_OEM_BITS_A1KDIS	(1 << 6)
 #define HV_OEM_BITS_ANEGNOW	(1 << 10)
 
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS		BME1000_REG(0, 26)
+#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
+#define HV_M_STATUS_SPEED_MASK	0x0300
+#define HV_M_STATUS_SPEED_1000	0x0200
+#define HV_M_STATUS_SPEED_100	0x0100
+#define HV_M_STATUS_LINK_UP	0x0040
+
 #define HV_LED_CONFIG		BME1000_REG(0, 30)
 
 #define	HV_KMRN_MODE_CTRL	BME1000_REG(BM_PORT_CTRL_PAGE, 16)

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.600 src/sys/dev/pci/if_wm.c:1.601
--- src/sys/dev/pci/if_wm.c:1.600	Tue Nov 20 04:04:42 2018
+++ src/sys/dev/pci/if_wm.c	Thu Nov 22 15:09:46 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.600 2018/11/20 04:04:42 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.601 2018/11/22 15:09:46 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.600 2018/11/20 04:04:42 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.601 2018/11/22 15:09:46 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -974,6 +974,8 @@ static void	wm_hv_phy_workaround_ich8lan
 static void	wm_lv_phy_workaround_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 *);
+static int	wm_link_stall_workaround_hv(struct wm_softc *);
 static void	wm_set_mdio_slow_mode_hv(struct wm_softc *);
 static void	wm_configure_k1_ich8lan(struct wm_softc *, int);
 static void	wm_reset_init_script_82575(struct wm_softc *);
@@ -8850,23 +8852,6 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
 			    ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
 		}
 
-		if ((sc->sc_phytype == WMPHY_82578)
-		    && (IFM_SUBTYPE(sc->sc_mii.mii_media_active)
-			== IFM_1000_T)) {
-
-			if ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0) {
-				delay(200*1000); /* XXX too big */
-
-				/* Link stall fix for link up */
-				wm_gmii_hv_writereg(sc->sc_dev, 1,
-				    HV_MUX_DATA_CTRL,
-				    HV_MUX_DATA_CTRL_GEN_TO_MAC
-				    | HV_MUX_DATA_CTRL_FORCE_SPEED);
-				wm_gmii_hv_writereg(sc->sc_dev, 1,
-				    HV_MUX_DATA_CTRL,
-				    HV_MUX_DATA_CTRL_GEN_TO_MAC);
-			}
-		}
 		/*
 		 * I217 Packet Loss issue:
 		 * ensure that FEXTNVM4 Beacon Duration is set correctly
@@ -8906,6 +8891,21 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
 				reg &= ~FEXTNVM6_K1_OFF_ENABLE;
 			CSR_WRITE(sc, WMREG_FEXTNVM6, reg);
 		}
+
+		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;
+		}
 	} else if (icr & ICR_RXSEQ) {
 		DPRINTF(WM_DEBUG_LINK, ("%s: LINK Receive sequence error\n",
 			device_xname(sc->sc_dev)));
@@ -14528,7 +14528,16 @@ out:
 	return;
 }
 
-/* WOL from S5 stops working */
+/*
+ *  wm_gig_downshift_workaround_ich8lan - WoL from S5 stops working
+ *  @sc: pointer to the HW structure
+ *
+ *  Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC),
+ *  LPLU, Gig disable, MDIC PHY reset):
+ *    1) Set Kumeran Near-end loopback
+ *    2) Clear Kumeran Near-end loopback
+ *  Should only be called for ICH8[m] devices with any 1G Phy.
+ */
 static void
 wm_gig_downshift_workaround_ich8lan(struct wm_softc *sc)
 {
@@ -14561,7 +14570,7 @@ wm_hv_phy_workaround_ich8lan(struct wm_s
 	if (sc->sc_phytype == WMPHY_82577)
 		wm_set_mdio_slow_mode_hv(sc);
 
-	/* (PCH rev.2) && (82577 && (phy rev 2 or 3)) */
+	/* XXX (PCH rev.2) && (82577 && (phy rev 2 or 3)) */
 
 	/* (82577 && (phy rev 1 or 2)) || (82578 & phy rev 1)*/
 
@@ -14594,6 +14603,10 @@ wm_hv_phy_workaround_ich8lan(struct wm_s
 	wm_k1_gig_workaround_hv(sc, 1);
 }
 
+/*
+ *  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)
 {
@@ -14602,7 +14615,11 @@ wm_lv_phy_workaround_ich8lan(struct wm_s
 		device_xname(sc->sc_dev), __func__));
 	KASSERT(sc->sc_type == WM_T_PCH2);
 
+	/* Set MDIO slow mode before any other MDIO access */
 	wm_set_mdio_slow_mode_hv(sc);
+
+	/* XXX set MSE higher to enable link to stay up when noise is high */
+	/* XXX drop link after 5 times MSE threshold was reached */
 }
 
 /**
@@ -14676,6 +14693,16 @@ update_fextnvm6:
 	return 0;
 }
 	
+/*
+ *  wm_k1_gig_workaround_hv - K1 Si workaround
+ *  @sc:   pointer to the HW structure
+ *  @link: link up bool flag
+ *
+ *  If K1 is enabled for 1Gbps, the MAC might stall when transitioning
+ *  from a lower speed.  This workaround disables K1 whenever link is at 1Gig
+ *  If link is down, the function will restore the default K1 setting located
+ *  in the NVM.
+ */
 static int
 wm_k1_gig_workaround_hv(struct wm_softc *sc, int link)
 {
@@ -14705,6 +14732,88 @@ wm_k1_gig_workaround_hv(struct wm_softc 
 	return 0;
 }
 
+/*
+ *  wm_k1_gig_workaround_lv - K1 Si workaround
+ *  @sc:   pointer to the HW structure
+ *
+ *  Workaround to set the K1 beacon duration for 82579 parts in 10Mbps
+ *  Disable K1 for 1000 and 100 speeds
+ */
+static int
+wm_k1_workaround_lv(struct wm_softc *sc)
+{
+	uint32_t reg;
+	int phyreg;
+	
+	if (sc->sc_type != WM_T_PCH2)
+		return 0;
+
+	/* Set K1 beacon duration based on 10Mbps speed */
+	phyreg = wm_gmii_hv_readreg(sc->sc_dev, 2, HV_M_STATUS);
+
+	if ((phyreg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
+	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
+		if (phyreg &
+		    (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) {
+			/* LV 1G/100 Packet drop issue wa  */
+			phyreg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_PM_CTRL);
+			phyreg &= ~HV_PM_CTRL_K1_ENA;
+			wm_gmii_hv_writereg(sc->sc_dev, 1, HV_PM_CTRL, phyreg);
+		} else {
+			/* For 10Mbps */
+			reg = CSR_READ(sc, WMREG_FEXTNVM4);
+			reg &= ~FEXTNVM4_BEACON_DURATION;
+			reg |= FEXTNVM4_BEACON_DURATION_16US;
+			CSR_WRITE(sc, WMREG_FEXTNVM4, reg);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *  wm_link_stall_workaround_hv - Si workaround
+ *  @sc: pointer to the HW structure
+ *
+ *  This function works around a Si bug where the link partner can get
+ *  a link up indication before the PHY does. If small packets are sent
+ *  by the link partner they can be placed in the packet buffer without
+ *  being properly accounted for by the PHY and will stall preventing
+ *  further packets from being received.  The workaround is to clear the
+ *  packet buffer after the PHY detects link up.
+ */
+static int
+wm_link_stall_workaround_hv(struct wm_softc *sc)
+{
+	int phyreg;
+
+	if (sc->sc_phytype != WMPHY_82578)
+		return 0;
+
+	/* Do not apply workaround if in PHY loopback bit 14 set */
+	phyreg =  wm_gmii_hv_readreg(sc->sc_dev, 2, MII_BMCR);
+	if ((phyreg & BMCR_LOOP) != 0)
+		return 0;
+
+	/* check if link is up and at 1Gbps */
+	phyreg = wm_gmii_hv_readreg(sc->sc_dev, 2, BM_CS_STATUS);
+	phyreg &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED
+	    | BM_CS_STATUS_SPEED_MASK;
+	if (phyreg != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED
+		| BM_CS_STATUS_SPEED_1000))
+		return 0;
+
+	delay(200 * 1000);	/* XXX too big */
+
+	/* flush the packets in the fifo buffer */
+	wm_gmii_hv_writereg(sc->sc_dev, 1, HV_MUX_DATA_CTRL,
+	    HV_MUX_DATA_CTRL_GEN_TO_MAC | HV_MUX_DATA_CTRL_FORCE_SPEED);
+	wm_gmii_hv_writereg(sc->sc_dev, 1, HV_MUX_DATA_CTRL,
+	    HV_MUX_DATA_CTRL_GEN_TO_MAC);
+
+	return 0;
+}
+
 static void
 wm_set_mdio_slow_mode_hv(struct wm_softc *sc)
 {
@@ -14715,6 +14824,14 @@ wm_set_mdio_slow_mode_hv(struct wm_softc
 	    reg | HV_KMRN_MDIO_SLOW);
 }
 
+/*
+ *  wm_configure_k1_ich8lan - Configure K1 power state
+ *  @sc: pointer to the HW structure
+ *  @enable: K1 state to configure
+ *
+ *  Configure the K1 power state based on the provided parameter.
+ *  Assumes semaphore already acquired.
+ */
 static void
 wm_configure_k1_ich8lan(struct wm_softc *sc, int k1_enable)
 {

Reply via email to