Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci - Make new wm_phy_post_reset() and use this func...



details:   https://anonhg.NetBSD.org/src/rev/5635a38cdae9
branches:  trunk
changeset: 825006:5635a38cdae9
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Mon Jun 26 04:22:46 2017 +0000

description:
- Make new wm_phy_post_reset() and use this function at all location after
  reseting phy.
- Move the location of calling wm_get_hw_control. Same as Linux.
- Add I219 specific wokaround for legacy interrupt. From OpenBSD.
- Move the location of calling wm_lplu_d0_disable().
- Fix latency calculation in wm_platform_pm_pch_lpt().
- Set OBFF water mark and enable OBFF on PCH_LPT and newer.

diffstat:

 sys/dev/pci/if_wm.c    |  202 ++++++++++++++++++++++++++++++++----------------
 sys/dev/pci/if_wmreg.h |   11 ++-
 2 files changed, 145 insertions(+), 68 deletions(-)

diffs (truncated from 366 to 300 lines):

diff -r 5e64f51dd586 -r 5635a38cdae9 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Mon Jun 26 04:18:14 2017 +0000
+++ b/sys/dev/pci/if_wm.c       Mon Jun 26 04:22:46 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.516 2017/06/26 04:18:14 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.517 2017/06/26 04:22:46 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.516 2017/06/26 04:18:14 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.517 2017/06/26 04:22:46 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -679,6 +679,7 @@
 static void    wm_get_auto_rd_done(struct wm_softc *);
 static void    wm_lan_init_done(struct wm_softc *);
 static void    wm_get_cfg_done(struct wm_softc *);
+static void    wm_phy_post_reset(struct wm_softc *);
 static void    wm_initialize_hardware_bits(struct wm_softc *);
 static uint32_t        wm_rxpbs_adjust_82580(uint32_t);
 static void    wm_reset_phy(struct wm_softc *);
@@ -930,6 +931,7 @@
 static void    wm_toggle_lanphypc_pch_lpt(struct wm_softc *);
 static int     wm_platform_pm_pch_lpt(struct wm_softc *, bool);
 static void    wm_pll_workaround_i210(struct wm_softc *);
+static void    wm_legacy_irq_quirk_spt(struct wm_softc *);
 
 CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -3659,6 +3661,47 @@
        }
 }
 
+void
+wm_phy_post_reset(struct wm_softc *sc)
+{
+       uint32_t reg;
+
+       /* This function is only for ICH8 and newer. */
+       if (sc->sc_type < WM_T_ICH8)
+               return;
+
+       if (wm_phy_resetisblocked(sc)) {
+               /* XXX */
+               device_printf(sc->sc_dev, " PHY is blocked\n");
+               return;
+       }
+
+       /* Allow time for h/w to get to quiescent state after reset */
+       delay(10*1000);
+
+       /* Perform any necessary post-reset workarounds */
+       if (sc->sc_type == WM_T_PCH)
+               wm_hv_phy_workaround_ich8lan(sc);
+       if (sc->sc_type == WM_T_PCH2)
+               wm_lv_phy_workaround_ich8lan(sc);
+
+       /* Clear the host wakeup bit after lcd reset */
+       if (sc->sc_type >= WM_T_PCH) {
+               reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
+                   BM_PORT_GEN_CFG);
+               reg &= ~BM_WUC_HOST_WU_BIT;
+               wm_gmii_hv_writereg(sc->sc_dev, 2,
+                   BM_PORT_GEN_CFG, reg);
+       }
+
+       /*
+        * XXX Configure the LCD with th extended configuration region
+        * in NVM
+        */
+
+       /* Configure the LCD with the OEM bits in NVM */
+}
+
 /* Init hardware bits */
 void
 wm_initialize_hardware_bits(struct wm_softc *sc)
@@ -3938,6 +3981,7 @@
        sc->phy.release(sc);
 
        wm_get_cfg_done(sc);
+       wm_phy_post_reset(sc);
 }
 
 static void
@@ -4371,6 +4415,9 @@
                break;
        }
 
+       if (phy_reset != 0)
+               wm_phy_post_reset(sc);
+
        if ((sc->sc_type == WM_T_82580)
            || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)) {
                /* clear global device reset status bit */
@@ -4403,15 +4450,6 @@
        if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211))
                wm_set_eee_i350(sc);
 
-       /* Clear the host wakeup bit after lcd reset */
-       if (sc->sc_type >= WM_T_PCH) {
-               reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
-                   BM_PORT_GEN_CFG);
-               reg &= ~BM_WUC_HOST_WU_BIT;
-               wm_gmii_hv_writereg(sc->sc_dev, 2,
-                   BM_PORT_GEN_CFG, reg);
-       }
-
        /*
         * For PCH, this write will make sure that any noise will be detected
         * as a CRC error and be dropped rather than show up as a bad packet
@@ -5091,6 +5129,10 @@
        ifp->if_collisions += CSR_READ(sc, WMREG_COLC);
        ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC);
 
+       /* AMT based hardware can now take control from firmware */
+       if ((sc->sc_flags & WM_F_HAS_AMT) != 0)
+               wm_get_hw_control(sc);
+
        /* PCH_SPT hardware workaround */
        if (sc->sc_type == WM_T_PCH_SPT)
                wm_flush_desc_rings(sc);
@@ -5098,9 +5140,9 @@
        /* Reset the chip to a known state. */
        wm_reset(sc);
 
-       /* AMT based hardware can now take control from firmware */
-       if ((sc->sc_flags & WM_F_HAS_AMT) != 0)
-               wm_get_hw_control(sc);
+       if ((sc->sc_type == WM_T_PCH_SPT) &&
+           pci_intr_type(sc->sc_pc, sc->sc_intrs[0]) == PCI_INTR_TYPE_INTX)
+               wm_legacy_irq_quirk_spt(sc);
 
        /* Init hardware bits */
        wm_initialize_hardware_bits(sc);
@@ -8528,7 +8570,7 @@
                        break;
                if (handled == 0) {
                        DPRINTF(WM_DEBUG_TX,
-                           ("%s: INTx: got intr\n", device_xname(sc->sc_dev)));
+                           ("%s: INTx: got intr\n",device_xname(sc->sc_dev)));
                }
                if (rndval == 0)
                        rndval = icr;
@@ -8934,34 +8976,7 @@
        case WM_T_PCH2:
        case WM_T_PCH_LPT:
        case WM_T_PCH_SPT:
-               /* Allow time for h/w to get to a quiescent state afer reset */
-               delay(10*1000);
-
-               if (sc->sc_type == WM_T_PCH)
-                       wm_hv_phy_workaround_ich8lan(sc);
-
-               if (sc->sc_type == WM_T_PCH2)
-                       wm_lv_phy_workaround_ich8lan(sc);
-
-               /* Clear the host wakeup bit after lcd reset */
-               if (sc->sc_type >= WM_T_PCH) {
-                       reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
-                           BM_PORT_GEN_CFG);
-                       reg &= ~BM_WUC_HOST_WU_BIT;
-                       wm_gmii_hv_writereg(sc->sc_dev, 2,
-                           BM_PORT_GEN_CFG, reg);
-               }
-
-               /*
-                * XXX Configure the LCD with th extended configuration region
-                * in NVM
-                */
-
-               /* Disable D0 LPLU. */
-               if (sc->sc_type >= WM_T_PCH)    /* PCH* */
-                       wm_lplu_d0_disable_pch(sc);
-               else
-                       wm_lplu_d0_disable(sc); /* ICH* */
+               wm_phy_post_reset(sc);
                break;
        default:
                panic("%s: unknown type\n", __func__);
@@ -9422,6 +9437,12 @@
        if ((ifp->if_flags & IFF_UP) == 0)
                return 0;
 
+       /* Disable D0 LPLU. */
+       if (sc->sc_type >= WM_T_PCH)    /* PCH* */
+               wm_lplu_d0_disable_pch(sc);
+       else
+               wm_lplu_d0_disable(sc); /* ICH* */
+
        sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
        sc->sc_ctrl |= CTRL_SLU;
        if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)
@@ -13764,15 +13785,36 @@
            | __SHIFTIN(link, LTRV_SNOOP_REQ) | LTRV_SEND;
        uint32_t rxa;
        uint16_t scale = 0, lat_enc = 0;
+       int32_t obff_hwm = 0;
        int64_t lat_ns, value;
        
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
 
        if (link) {
+               uint16_t max_snoop, max_nosnoop, max_ltr_enc;
+               uint32_t status;
+               uint16_t speed;
                pcireg_t preg;
-               uint16_t max_snoop, max_nosnoop, max_ltr_enc;
-
+
+               status = CSR_READ(sc, WMREG_STATUS);
+               switch (__SHIFTOUT(status, STATUS_SPEED)) {
+               case STATUS_SPEED_10:
+                       speed = 10;
+                       break;
+               case STATUS_SPEED_100:
+                       speed = 100;
+                       break;
+               case STATUS_SPEED_1000:
+                       speed = 1000;
+                       break;
+               default:
+                       device_printf(sc->sc_dev, "Unknown speed "
+                           "(status = %08x)\n", status);
+                       return -1;
+               }
+
+               /* Rx Packet Buffer Allocation size (KB) */
                rxa = CSR_READ(sc, WMREG_PBA) & PBA_RXA_MASK;
 
                /*
@@ -13785,31 +13827,12 @@
                 * 1=2^5ns, 2=2^10ns,...5=2^25ns.
                 */
                lat_ns = ((int64_t)rxa * 1024 -
-                   (2 * (int64_t)sc->sc_ethercom.ec_if.if_mtu)) * 8 * 1000;
+                   (2 * ((int64_t)sc->sc_ethercom.ec_if.if_mtu
+                       + ETHER_HDR_LEN))) * 8 * 1000;
                if (lat_ns < 0)
                        lat_ns = 0;
-               else {
-                       uint32_t status;
-                       uint16_t speed;
-
-                       status = CSR_READ(sc, WMREG_STATUS);
-                       switch (__SHIFTOUT(status, STATUS_SPEED)) {
-                       case STATUS_SPEED_10:
-                               speed = 10;
-                               break;
-                       case STATUS_SPEED_100:
-                               speed = 100;
-                               break;
-                       case STATUS_SPEED_1000:
-                               speed = 1000;
-                               break;
-                       default:
-                               printf("%s: Unknown speed (status = %08x)\n",
-                                   device_xname(sc->sc_dev), status);
-                               return -1;
-                       }
+               else
                        lat_ns /= speed;
-               }
                value = lat_ns;
 
                while (value > LTRV_VALUE) {
@@ -13833,12 +13856,39 @@
 
                if (lat_enc > max_ltr_enc) {
                        lat_enc = max_ltr_enc;
+                       lat_ns = __SHIFTOUT(lat_enc, PCI_LTR_MAXSNOOPLAT_VAL)
+                           * PCI_LTR_SCALETONS(
+                                   __SHIFTOUT(lat_enc,
+                                       PCI_LTR_MAXSNOOPLAT_SCALE));
+               }
+
+               if (lat_ns) {
+                       lat_ns *= speed * 1000;
+                       lat_ns /= 8;
+                       lat_ns /= 1000000000;
+                       obff_hwm = (int32_t)(rxa - lat_ns);
+               }
+               if ((obff_hwm < 0) || (obff_hwm > SVT_OFF_HWM)) {
+                       device_printf(sc->sc_dev, "Invalid high water mark %d"
+                           "(rxa = %d, lat_ns = %d)\n",
+                           obff_hwm, (int32_t)rxa, (int32_t)lat_ns);
+                       return -1;
                }
        }
        /* Snoop and No-Snoop latencies the same */
        reg |= lat_enc | __SHIFTIN(lat_enc, LTRV_NONSNOOP);
        CSR_WRITE(sc, WMREG_LTRV, reg);
 
+       /* Set OBFF high water mark */



Home | Main Index | Thread Index | Old Index