Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Add some workarounds which use EMI register or EEE r...



details:   https://anonhg.NetBSD.org/src/rev/5bd077b9622f
branches:  trunk
changeset: 996397:5bd077b9622f
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Jan 31 05:20:49 2019 +0000

description:
Add some workarounds which use EMI register or EEE related:
 - PCH only: Add workaround for link disconnects on a busy hub in half duplex.
 - PCH and PCH2 only: Set MSE higher to enable link to stay up when noise is
   high.
 - PCH2 only: Drop link after 5 times MSE threshold was reached.
 - PCH2 only: Set EEE LPI Update Timer to 200usec.
 - For PCH2 and newer: When connected at 10Mbps half-duplex, some parts are
   excessively aggressive resulting in many collisions. To avoid this, increase
   the IPG and reduce Rx latency in the PHY.
 - For I21[789] and if EEE is enabled: Disable LPLU if both link partners
   support 100BaseT EEE and 100Full is advertised on both ends of the link, and
   enable Auto Enable LPI since there will be no driver to enable LPI while in
   Sx.

diffstat:

 sys/dev/mii/inbmphyreg.h |   16 ++-
 sys/dev/pci/if_wm.c      |  235 ++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/pci/if_wmreg.h   |    5 +-
 3 files changed, 228 insertions(+), 28 deletions(-)

diffs (truncated from 475 to 300 lines):

diff -r 569436b2ba62 -r 5bd077b9622f sys/dev/mii/inbmphyreg.h
--- a/sys/dev/mii/inbmphyreg.h  Thu Jan 31 03:25:29 2019 +0000
+++ b/sys/dev/mii/inbmphyreg.h  Thu Jan 31 05:20:49 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: inbmphyreg.h,v 1.16 2019/01/07 01:43:22 msaitoh Exp $  */
+/*     $NetBSD: inbmphyreg.h,v 1.17 2019/01/31 05:20:49 msaitoh Exp $  */
 /*******************************************************************************
 Copyright (c) 2001-2015, Intel Corporation 
 All rights reserved.
@@ -81,15 +81,21 @@
 /* Extended Management Interface (EMI) Registers */
 #define I82579_EMI_ADDR        0x10
 #define I82579_EMI_DATA        0x11
+#define I82579_LPI_UPDATE_TIMER        0x4805 /* in 40ns units + 40 ns base value */
+#define I82579_MSE_THRESHOLD   0x084F /* 82579 Mean Square Error Threshold */
+#define I82577_MSE_THRESHOLD   0x0887 /* 82577 Mean Square Error Threshold */
+#define I82579_MSE_LINK_DOWN   0x2411 /* MSE count before dropping link */
 #define I82579_EEE_ADVERTISEMENT 0x040e  /* IEEE MMD Register 7.60 */
 #define I82579_EEE_LP_ABILITY  0x040f   /* IEEE MMD Register 7.61 */
 #define I82579_EEE_PCS_STATUS  0x182e
+#define I82579_RX_CONFIG       0x3412 /* Receive configuration */
 #define I82579_LPI_PLL_SHUT    0x4412
-#define I82579_LPI_PLL_SHUT_100                __BIT(2) /* 100M LPI PLL Shut Enable */
+#define I82579_LPI_PLL_SHUT_100        __BIT(2) /* 100M LPI PLL Shut Enable */
 #define I217_EEE_PCS_STATUS    0x9401   /* IEEE MMD Register 3.1 */
 #define I217_EEE_CAPABILITY    0x8000   /* IEEE MMD Register 3.20 */
 #define I217_EEE_ADVERTISEMENT 0x8001   /* IEEE MMD Register 7.60 */
 #define I217_EEE_LP_ABILITY    0x8002   /* IEEE MMD Register 7.61 */
+#define I217_RX_CONFIG         0xb20c   /* Receive configuration */
 
 /* BM PHY Copper Specific Status */
 #define BM_CS_STATUS           BME1000_REG(0, 17)
@@ -134,6 +140,7 @@
 #define        CV_SMB_CTRL_FORCE_SMBUS __BIT(0)
 
 #define        HV_PM_CTRL              BME1000_REG(770, 17)
+#define HV_PM_CTRL_K1_CLK_REQ  __BIT(9)
 #define        HV_PM_CTRL_K1_ENA       __BIT(14)
 
 #define        I217_INBAND_CTRL        BME1000_REG(770, 18)
@@ -154,6 +161,9 @@
 #define        I217_MEMPWR             BME1000_REG(772, 26)
 #define        I217_MEMPWR_DISABLE_SMB_RELEASE         0x0010
 
+#define I217_PLL_CLOCK_GATE_REG        BME1000_REG(772, 28)
+#define I217_PLL_CLOCK_GATE_MASK       0x07FF
+
 #define        I217_CFGREG             BME1000_REG(772, 29)
 #define I217_CGFREG_ENABLE_MTA_RESET   0x0002
 
@@ -161,6 +171,8 @@
 #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 I218_ULP_CONFIG1       BME1000_REG(779, 16)
 #define I218_ULP_CONFIG1_START         __BIT(0)
 #define I218_ULP_CONFIG1_IND           __BIT(2)
diff -r 569436b2ba62 -r 5bd077b9622f sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Jan 31 03:25:29 2019 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Jan 31 05:20:49 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.620 2019/01/25 08:04:07 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.621 2019/01/31 05:20:49 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.620 2019/01/25 08:04:07 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.621 2019/01/31 05:20:49 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -4008,6 +4008,7 @@
 int
 wm_phy_post_reset(struct wm_softc *sc)
 {
+       device_t dev = sc->sc_dev;
        uint16_t reg;
        int rv = 0;
 
@@ -4017,7 +4018,7 @@
 
        if (wm_phy_resetisblocked(sc)) {
                /* XXX */
-               device_printf(sc->sc_dev, "PHY is blocked\n");
+               device_printf(dev, "PHY is blocked\n");
                return -1;
        }
 
@@ -4034,9 +4035,9 @@
 
        /* Clear the host wakeup bit after lcd reset */
        if (sc->sc_type >= WM_T_PCH) {
-               wm_gmii_hv_readreg(sc->sc_dev, 2, BM_PORT_GEN_CFG, &reg);
+               wm_gmii_hv_readreg(dev, 2, BM_PORT_GEN_CFG, &reg);
                reg &= ~BM_WUC_HOST_WU_BIT;
-               wm_gmii_hv_writereg(sc->sc_dev, 2, BM_PORT_GEN_CFG, reg);
+               wm_gmii_hv_writereg(dev, 2, BM_PORT_GEN_CFG, reg);
        }
 
        /* Configure the LCD with the extended configuration region in NVM */
@@ -4052,7 +4053,13 @@
                        delay(10 * 1000);
                        wm_gate_hw_phy_config_ich8lan(sc, false);
                }
-               /* XXX Set EEE LPI Update Timer to 200usec */   
+               /* Set EEE LPI Update Timer to 200usec */       
+               rv = sc->phy.acquire(sc);
+               if (rv)
+                       return rv;
+               rv = wm_write_emi_reg_locked(dev,
+                   I82579_LPI_UPDATE_TIMER, 0x1387);
+               sc->phy.release(sc);
        }
 
        return rv;
@@ -8953,19 +8960,21 @@
 static void
 wm_linkintr_gmii(struct wm_softc *sc, uint32_t icr)
 {
+       device_t dev = sc->sc_dev;
        uint32_t status, reg;
        bool link;
+       int rv;
 
        KASSERT(WM_CORE_LOCKED(sc));
 
-       DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
+       DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(dev),
                __func__));
 
        if ((icr & ICR_LSC) == 0) {
                if (icr & ICR_RXSEQ)
                        DPRINTF(WM_DEBUG_LINK,
                            ("%s: LINK Receive sequence error\n",
-                               device_xname(sc->sc_dev)));
+                               device_xname(dev)));
                return;
        }
 
@@ -8974,11 +8983,11 @@
        link = status & STATUS_LU;
        if (link)
                DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n",
-                       device_xname(sc->sc_dev),
+                       device_xname(dev),
                        (status & STATUS_FD) ? "FDX" : "HDX"));
        else
                DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n",
-                       device_xname(sc->sc_dev)));
+                       device_xname(dev)));
        if ((sc->sc_type == WM_T_ICH8) && (link == false))
                wm_gig_downshift_workaround_ich8lan(sc);
 
@@ -8987,7 +8996,7 @@
                wm_kmrn_lock_loss_workaround_ich8lan(sc);
        }
        DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> mii_pollstat\n",
-               device_xname(sc->sc_dev)));
+               device_xname(dev)));
        mii_pollstat(&sc->sc_mii);
        if (sc->sc_type == WM_T_82543) {
                int miistatus, active;
@@ -9030,6 +9039,117 @@
        }
 
        /*
+        * When connected at 10Mbps half-duplex, some parts are excessively
+        * aggressive resulting in many collisions. To avoid this, increase
+        * the IPG and reduce Rx latency in the PHY.
+        */
+       if ((sc->sc_type >= WM_T_PCH2) && (sc->sc_type <= WM_T_PCH_CNP)
+           && link) {
+               uint32_t tipg_reg;
+               uint32_t speed = __SHIFTOUT(status, STATUS_SPEED);
+               bool fdx;
+               uint16_t emi_addr, emi_val;
+
+               tipg_reg = CSR_READ(sc, WMREG_TIPG);
+               tipg_reg &= ~TIPG_IPGT_MASK;
+               fdx = status & STATUS_FD;
+
+               if (!fdx && (speed == STATUS_SPEED_10)) {
+                       tipg_reg |= 0xff;
+                       /* Reduce Rx latency in analog PHY */
+                       emi_val = 0;
+               } else if ((sc->sc_type >= WM_T_PCH_SPT) &&
+                   fdx && speed != STATUS_SPEED_1000) {
+                       tipg_reg |= 0xc;
+                       emi_val = 1;
+               } else {
+                       /* Roll back the default values */
+                       tipg_reg |= 0x08;
+                       emi_val = 1;
+               }
+
+               CSR_WRITE(sc, WMREG_TIPG, tipg_reg);
+
+               rv = sc->phy.acquire(sc);
+               if (rv)
+                       return;
+
+               if (sc->sc_type == WM_T_PCH2)
+                       emi_addr = I82579_RX_CONFIG;
+               else
+                       emi_addr = I217_RX_CONFIG;
+               rv = wm_write_emi_reg_locked(dev, emi_addr, emi_val);
+
+               if (sc->sc_type >= WM_T_PCH_LPT) {
+                       uint16_t phy_reg;
+
+                       sc->phy.readreg_locked(dev, 2,
+                           I217_PLL_CLOCK_GATE_REG, &phy_reg);
+                       phy_reg &= ~I217_PLL_CLOCK_GATE_MASK;
+                       if (speed == STATUS_SPEED_100
+                           || speed == STATUS_SPEED_10)
+                               phy_reg |= 0x3e8;
+                       else
+                               phy_reg |= 0xfa;
+                       sc->phy.writereg_locked(dev, 2,
+                           I217_PLL_CLOCK_GATE_REG, phy_reg);
+
+                       if (speed == STATUS_SPEED_1000) {
+                               sc->phy.readreg_locked(dev, 2,
+                                   HV_PM_CTRL, &phy_reg);
+
+                               phy_reg |= HV_PM_CTRL_K1_CLK_REQ;
+
+                               sc->phy.writereg_locked(dev, 2,
+                                   HV_PM_CTRL, phy_reg);
+                       }
+               }
+               sc->phy.release(sc);
+
+               if (rv)
+                       return;
+
+               if (sc->sc_type >= WM_T_PCH_SPT) {
+                       uint16_t data, ptr_gap;
+
+                       if (speed == STATUS_SPEED_1000) {
+                               rv = sc->phy.acquire(sc);
+                               if (rv)
+                                       return;
+
+                               rv = sc->phy.readreg_locked(dev, 2,
+                                   I219_UNKNOWN1, &data);
+                               if (rv) {
+                                       sc->phy.release(sc);
+                                       return;
+                               }
+
+                               ptr_gap = (data & (0x3ff << 2)) >> 2;
+                               if (ptr_gap < 0x18) {
+                                       data &= ~(0x3ff << 2);
+                                       data |= (0x18 << 2);
+                                       rv = sc->phy.writereg_locked(dev,
+                                           2, I219_UNKNOWN1, data);
+                               }
+                               sc->phy.release(sc);
+                               if (rv)
+                                       return;
+                       } else {
+                               rv = sc->phy.acquire(sc);
+                               if (rv)
+                                       return;
+
+                               rv = sc->phy.writereg_locked(dev, 2,
+                                   I219_UNKNOWN1, 0xc023);
+                               sc->phy.release(sc);
+                               if (rv)
+                                       return;
+
+                       }
+               }
+       }
+
+       /*
         * I217 Packet Loss issue:
         * ensure that FEXTNVM4 Beacon Duration is set correctly
         * on power up.
@@ -14695,11 +14815,16 @@
 static void
 wm_suspend_workarounds_ich8lan(struct wm_softc *sc)
 {
+       device_t dev = sc->sc_dev;
+       struct ethercom *ec = &sc->sc_ethercom;
        uint32_t phy_ctrl;
+       int rv;
 
        phy_ctrl = CSR_READ(sc, WMREG_PHY_CTRL);
        phy_ctrl |= PHY_CTRL_GBE_DIS;
 
+       KASSERT((sc->sc_type >= WM_T_ICH8) && (sc->sc_type <= WM_T_PCH_CNP));
+



Home | Main Index | Thread Index | Old Index