Module Name:    src
Committed By:   msaitoh
Date:           Wed Sep 16 15:04:02 UTC 2020

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

Log Message:
 Add a workaround for jumbo frame on PCH2 and newer. Tested by chs@.

- Add wm_lv_jumbo_workaround_ich8lan() and use it. From FreeBSD.

  XXX For KUMCTRLSTA_OFFSET_HD_CTRL register modification, it's doubtful.
  FreeBSD and Linux do the same thing that they set the same value on both
  jumbo frame's enable case and the disable case. It seems the default value
  is 0x0b0c and it's not changed on the enable case, so it might be a bug
  on the enable case or the modification is not required.

- Rename I219_UNKNOWN1 to I82579_UNKNOWN1.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/mii/inbmphyreg.h
cvs rdiff -u -r1.687 -r1.688 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.119 -r1.120 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/mii/inbmphyreg.h
diff -u src/sys/dev/mii/inbmphyreg.h:1.19 src/sys/dev/mii/inbmphyreg.h:1.20
--- src/sys/dev/mii/inbmphyreg.h:1.19	Wed Dec 11 07:33:55 2019
+++ src/sys/dev/mii/inbmphyreg.h	Wed Sep 16 15:04:01 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: inbmphyreg.h,v 1.19 2019/12/11 07:33:55 msaitoh Exp $	*/
+/*	$NetBSD: inbmphyreg.h,v 1.20 2020/09/16 15:04:01 msaitoh Exp $	*/
 /*******************************************************************************
 Copyright (c) 2001-2015, Intel Corporation 
 All rights reserved.
@@ -136,6 +136,8 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #define	BM_PORT_GEN_CFG		BME1000_REG(BM_PORT_CTRL_PAGE, 17)
 
+#define	I82579_DFT_CTRL		BME1000_REG(BM_PORT_CTRL_PAGE, 20)
+
 #define	CV_SMB_CTRL		BME1000_REG(BM_PORT_CTRL_PAGE, 23)
 #define	CV_SMB_CTRL_FORCE_SMBUS	__BIT(0)
 
@@ -180,7 +182,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define HV_MUX_DATA_CTRL_FORCE_SPEED	(1 << 2)
 #define HV_MUX_DATA_CTRL_GEN_TO_MAC	(1 << 10)
 
-#define I219_UNKNOWN1		BME1000_REG(776, 20)
+#define I82579_UNKNOWN1		BME1000_REG(776, 20)
+#define I82579_TX_PTR_GAP	0x1f
 
 #define I218_ULP_CONFIG1	BME1000_REG(779, 16)
 #define I218_ULP_CONFIG1_START		__BIT(0)

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.687 src/sys/dev/pci/if_wm.c:1.688
--- src/sys/dev/pci/if_wm.c:1.687	Tue Sep 15 08:39:04 2020
+++ src/sys/dev/pci/if_wm.c	Wed Sep 16 15:04:01 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.687 2020/09/15 08:39:04 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.688 2020/09/16 15:04:01 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.687 2020/09/15 08:39:04 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.688 2020/09/16 15:04:01 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -1016,6 +1016,8 @@ static int	wm_kmrn_lock_loss_workaround_
 static void	wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
 static int	wm_hv_phy_workarounds_ich8lan(struct wm_softc *);
 static void	wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *);
+static void	wm_copy_rx_addrs_to_phy_ich8lan_locked(struct wm_softc *);
+static int	wm_lv_jumbo_workaround_ich8lan(struct wm_softc *, bool);
 static int	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);
@@ -3802,7 +3804,7 @@ wm_set_filter(struct wm_softc *sc)
 	struct ether_multistep step;
 	bus_addr_t mta_reg;
 	uint32_t hash, reg, bit;
-	int i, size, ralmax;
+	int i, size, ralmax, rv;
 
 	DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
 		device_xname(sc->sc_dev), __func__));
@@ -3928,6 +3930,17 @@ wm_set_filter(struct wm_softc *sc)
 	sc->sc_rctl |= RCTL_MPE;
 
  setit:
+	if (sc->sc_type >= WM_T_PCH2) {
+		if (((ec->ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
+		    && (ifp->if_mtu > ETHERMTU))
+			rv = wm_lv_jumbo_workaround_ich8lan(sc, true);
+		else
+			rv = wm_lv_jumbo_workaround_ich8lan(sc, false);
+		if (rv != 0)
+			device_printf(sc->sc_dev,
+			    "Failed to do workaround for jumbo frame.\n");
+	}
+
 	CSR_WRITE(sc, WMREG_RCTL, sc->sc_rctl);
 }
 
@@ -9312,7 +9325,7 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
 					return;
 
 				rv = sc->phy.readreg_locked(dev, 2,
-				    I219_UNKNOWN1, &data);
+				    I82579_UNKNOWN1, &data);
 				if (rv) {
 					sc->phy.release(sc);
 					return;
@@ -9323,7 +9336,7 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
 					data &= ~(0x3ff << 2);
 					data |= (0x18 << 2);
 					rv = sc->phy.writereg_locked(dev,
-					    2, I219_UNKNOWN1, data);
+					    2, I82579_UNKNOWN1, data);
 				}
 				sc->phy.release(sc);
 				if (rv)
@@ -9334,7 +9347,7 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
 					return;
 
 				rv = sc->phy.writereg_locked(dev, 2,
-				    I219_UNKNOWN1, 0xc023);
+				    I82579_UNKNOWN1, 0xc023);
 				sc->phy.release(sc);
 				if (rv)
 					return;
@@ -15882,18 +15895,31 @@ release:
 static void
 wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *sc)
 {
+
+	DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+		device_xname(sc->sc_dev), __func__));
+
+	if (sc->phy.acquire(sc) != 0)
+		return;
+
+	wm_copy_rx_addrs_to_phy_ich8lan_locked(sc);
+
+	sc->phy.release(sc);
+}
+
+static void
+wm_copy_rx_addrs_to_phy_ich8lan_locked(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__));
+		device_xname(dev), __func__));
 
-	if (sc->phy.acquire(sc) != 0)
-		return;
 	if (wm_enable_phy_wakeup_reg_access_bm(dev, &wuce) != 0)
-		goto release;
+		return;
 
 	/* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */
 	count = wm_rar_count(sc);
@@ -15913,9 +15939,182 @@ wm_copy_rx_addrs_to_phy_ich8lan(struct w
 	}
 
 	wm_disable_phy_wakeup_reg_access_bm(dev, &wuce);
+}
 
-release:
+/*
+ *  wm_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
+ *  with 82579 PHY
+ *  @enable: flag to enable/disable workaround when enabling/disabling jumbos
+ */
+static int
+wm_lv_jumbo_workaround_ich8lan(struct wm_softc *sc, bool enable)
+{
+	device_t dev = sc->sc_dev;
+	int rar_count;
+	int rv;
+	uint32_t mac_reg;
+	uint16_t dft_ctrl, data;
+	uint16_t i;
+
+	DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+		device_xname(dev), __func__));
+
+	if (sc->sc_type < WM_T_PCH2)
+		return 0;
+
+	/* Acquire PHY semaphore */
+	rv = sc->phy.acquire(sc);
+	if (rv != 0)
+		return rv;
+
+	/* Disable Rx path while enabling/disabling workaround */
+	sc->phy.readreg_locked(dev, 2, I82579_DFT_CTRL, &dft_ctrl);
+	if (rv != 0)
+		goto out;
+	rv = sc->phy.writereg_locked(dev, 2, I82579_DFT_CTRL,
+	    dft_ctrl | (1 << 14));
+	if (rv != 0)
+		goto out;
+
+	if (enable) {
+		/* Write Rx addresses (rar_entry_count for RAL/H, and
+		 * SHRAL/H) and initial CRC values to the MAC
+		 */
+		rar_count = wm_rar_count(sc);
+		for (i = 0; i < rar_count; i++) {
+			uint8_t mac_addr[ETHER_ADDR_LEN] = {0};
+			uint32_t addr_high, addr_low;
+
+			addr_high = CSR_READ(sc, WMREG_CORDOVA_RAH(i));
+			if (!(addr_high & RAL_AV))
+				continue;
+			addr_low = CSR_READ(sc, WMREG_CORDOVA_RAL(i));
+			mac_addr[0] = (addr_low & 0xFF);
+			mac_addr[1] = ((addr_low >> 8) & 0xFF);
+			mac_addr[2] = ((addr_low >> 16) & 0xFF);
+			mac_addr[3] = ((addr_low >> 24) & 0xFF);
+			mac_addr[4] = (addr_high & 0xFF);
+			mac_addr[5] = ((addr_high >> 8) & 0xFF);
+
+			CSR_WRITE(sc, WMREG_PCH_RAICC(i),
+			    ~ether_crc32_le(mac_addr, ETHER_ADDR_LEN));
+		}
+
+		/* Write Rx addresses to the PHY */
+		wm_copy_rx_addrs_to_phy_ich8lan_locked(sc);
+	}
+
+	/*
+	 * If enable ==
+	 *	true: Enable jumbo frame workaround in the MAC.
+	 *	false: Write MAC register values back to h/w defaults.
+	 */
+	mac_reg = CSR_READ(sc, WMREG_FFLT_DBG);
+	if (enable) {
+		mac_reg &= ~(1 << 14);
+		mac_reg |= (7 << 15);
+	} else
+		mac_reg &= ~(0xf << 14);
+	CSR_WRITE(sc, WMREG_FFLT_DBG, mac_reg);
+
+	mac_reg = CSR_READ(sc, WMREG_RCTL);
+	if (enable) {
+		mac_reg |= RCTL_SECRC;
+		sc->sc_rctl |= RCTL_SECRC;
+		sc->sc_flags |= WM_F_CRC_STRIP;
+	} else {
+		mac_reg &= ~RCTL_SECRC;
+		sc->sc_rctl &= ~RCTL_SECRC;
+		sc->sc_flags &= ~WM_F_CRC_STRIP;
+	}
+	CSR_WRITE(sc, WMREG_RCTL, mac_reg);
+
+	rv = wm_kmrn_readreg_locked(sc, KUMCTRLSTA_OFFSET_CTRL, &data);
+	if (rv != 0)
+		goto out;
+	if (enable)
+		data |= 1 << 0;
+	else
+		data &= ~(1 << 0);
+	rv = wm_kmrn_writereg_locked(sc, KUMCTRLSTA_OFFSET_CTRL, data);
+	if (rv != 0)
+		goto out;
+
+	rv = wm_kmrn_readreg_locked(sc, KUMCTRLSTA_OFFSET_HD_CTRL, &data);
+	if (rv != 0)
+		goto out;
+	/*
+	 * XXX FreeBSD and Linux do the same thing that they set the same value
+	 * on both the enable case and the disable case. Is it correct?
+	 */
+	data &= ~(0xf << 8);
+	data |= (0xb << 8);
+	rv = wm_kmrn_writereg_locked(sc, KUMCTRLSTA_OFFSET_HD_CTRL, data);
+	if (rv != 0)
+		goto out;
+
+	/*
+	 * If enable ==
+	 *	true: Enable jumbo frame workaround in the PHY.
+	 *	false: Write PHY register values back to h/w defaults.
+	 */
+	rv = sc->phy.readreg_locked(dev, 2, BME1000_REG(769, 23), &data);
+	if (rv != 0)
+		goto out;
+	data &= ~(0x7F << 5);
+	if (enable)
+		data |= (0x37 << 5);
+	rv = sc->phy.writereg_locked(dev, 2, BME1000_REG(769, 23), data);
+	if (rv != 0)
+		goto out;
+
+	rv = sc->phy.readreg_locked(dev, 2, BME1000_REG(769, 16), &data);
+	if (rv != 0)
+		goto out;
+	if (enable)
+		data &= ~(1 << 13);
+	else
+		data |= (1 << 13);
+	rv = sc->phy.writereg_locked(dev, 2, BME1000_REG(769, 16), data);
+	if (rv != 0)
+		goto out;
+
+	rv = sc->phy.readreg_locked(dev, 2, I82579_UNKNOWN1, &data);
+	if (rv != 0)
+		goto out;
+	data &= ~(0x3FF << 2);
+	if (enable)
+		data |= (I82579_TX_PTR_GAP << 2);
+	else
+		data |= (0x8 << 2);
+	rv = sc->phy.writereg_locked(dev, 2, I82579_UNKNOWN1, data);
+	if (rv != 0)
+		goto out;
+
+	rv = sc->phy.writereg_locked(dev, 2, BME1000_REG(776, 23),
+	    enable ? 0xf100 : 0x7e00);
+	if (rv != 0)
+		goto out;
+
+	rv = sc->phy.readreg_locked(dev, 2, HV_PM_CTRL, &data);
+	if (rv != 0)
+		goto out;
+	if (enable)
+		data |= 1 << 10;
+	else
+		data &= ~(1 << 10);
+	rv = sc->phy.writereg_locked(dev, 2, HV_PM_CTRL, data);
+	if (rv != 0)
+		goto out;
+
+	/* Re-enable Rx path after enabling/disabling workaround */
+	rv = sc->phy.writereg_locked(dev, 2, I82579_DFT_CTRL,
+	    dft_ctrl & ~(1 << 14));
+
+out:
 	sc->phy.release(sc);
+
+	return rv;
 }
 
 /*

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.119 src/sys/dev/pci/if_wmreg.h:1.120
--- src/sys/dev/pci/if_wmreg.h:1.119	Wed Jan  8 03:51:37 2020
+++ src/sys/dev/pci/if_wmreg.h	Wed Sep 16 15:04:02 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.119 2020/01/08 03:51:37 msaitoh Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.120 2020/09/16 15:04:02 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -1379,7 +1379,10 @@ struct livengood_tcpip_ctxdesc {
 #define WMREG_FEXTNVM11	0x5bbc	/* Future Extended NVM 11 */
 #define FEXTNVM11_DIS_MULRFIX	__BIT(13)	/* Disable MULR fix */
 
+#define WMREG_FFLT_DBG	0x05F04 /* Debug Register */
+
 #define WMREG_CRC_OFFSET 0x5f50
+#define WMREG_PCH_RAICC(x)	(WMREG_CRC_OFFSET + (x) * 4)
 
 #define WMREG_EEC	0x12010
 #define EEC_FLASH_DETECTED (1U << 19)	/* FLASH */

Reply via email to