Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev - Add wm_k1_workaround_lv() from FreeBSD. It's PCH2 ...
details: https://anonhg.NetBSD.org/src/rev/d48328339d6e
branches: trunk
changeset: 446077:d48328339d6e
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Thu Nov 22 15:09:45 2018 +0000
description:
- 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.
diffstat:
sys/dev/mii/inbmphyreg.h | 17 ++++-
sys/dev/pci/if_wm.c | 159 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 154 insertions(+), 22 deletions(-)
diffs (282 lines):
diff -r c170e5ed36fb -r d48328339d6e sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h Thu Nov 22 15:06:00 2018 +0000
+++ b/sys/dev/mii/inbmphyreg.h Thu Nov 22 15:09:45 2018 +0000
@@ -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 @@
#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 @@
#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)
diff -r c170e5ed36fb -r d48328339d6e sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Thu Nov 22 15:06:00 2018 +0000
+++ b/sys/dev/pci/if_wm.c Thu Nov 22 15:09:45 2018 +0000
@@ -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_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 @@
((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 @@
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 @@
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 @@
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_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 @@
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 @@
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 @@
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 @@
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)
{
Home |
Main Index |
Thread Index |
Old Index