Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Fix fiber link problem (PR#44776 and PR#30880). ...



details:   https://anonhg.NetBSD.org/src/rev/848656703229
branches:  trunk
changeset: 797853:848656703229
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Jul 31 03:50:09 2014 +0000

description:
Fix fiber link problem (PR#44776 and PR#30880). Tested with 82543GC, 82544EI,
82545EM, 82546GB 82571EB and 82572EI fiber cards.
- Don't use the RXCFG interrupt. It's not required and the interrupt is very
  heavy (a lot of interrupts). Same as {Free,Open}BSD.
- Modify wm_tbi_mediachange() to be close to em_setup_fiber_serdes_link()
  of {Free,Open}BSD. At least, don't forget to set duplex setting.
- WM_T_82545 is not 1000base-SX but 1000base-LX. Same as FreeBSD. Tested with
  my own 82545EM card.

diffstat:

 sys/dev/pci/if_wm.c    |  99 ++++++++++++++++++-------------------------------
 sys/dev/pci/if_wmreg.h |   5 ++-
 2 files changed, 41 insertions(+), 63 deletions(-)

diffs (218 lines):

diff -r 5c47728889ee -r 848656703229 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Jul 31 03:39:35 2014 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Jul 31 03:50:09 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.284 2014/07/31 02:54:46 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.285 2014/07/31 03:50:09 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.284 2014/07/31 02:54:46 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.285 2014/07/31 03:50:09 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -375,8 +375,6 @@
        int sc_tbi_linkup;              /* TBI link status */
        int sc_tbi_anegticks;           /* autonegotiation ticks */
        int sc_tbi_ticks;               /* tbi ticks */
-       int sc_tbi_nrxcfg;              /* count of ICR_RXCFG */
-       int sc_tbi_lastnrxcfg;          /* count of ICR_RXCFG (on last tick) */
 
        int sc_mchash_type;             /* multicast filter offset */
 
@@ -3853,15 +3851,10 @@
                reg |= RXCSUM_IPV6OFL | RXCSUM_TUOFL;
        CSR_WRITE(sc, WMREG_RXCSUM, reg);
 
-       /* Reset TBI's RXCFG count */
-       sc->sc_tbi_nrxcfg = sc->sc_tbi_lastnrxcfg = 0;
-
        /* Set up the interrupt registers. */
        CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
        sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
            ICR_RXO | ICR_RXT0;
-       if ((sc->sc_flags & WM_F_HAS_MII) == 0)
-               sc->sc_icr |= ICR_RXCFG;
        CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
 
        if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
@@ -5658,11 +5651,6 @@
                        sc->sc_tbi_linkup = 0;
                }
                wm_tbi_set_linkled(sc);
-       } else if (icr & ICR_RXCFG) {
-               DPRINTF(WM_DEBUG_LINK, ("%s: LINK: receiving /C/\n",
-                   device_xname(sc->sc_dev)));
-               sc->sc_tbi_nrxcfg++;
-               wm_check_for_link(sc);
        } else if (icr & ICR_RXSEQ) {
                DPRINTF(WM_DEBUG_LINK,
                    ("%s: LINK: Receive sequence error\n",
@@ -5737,7 +5725,7 @@
 #endif
                wm_txintr(sc);
 
-               if (icr & (ICR_LSC|ICR_RXSEQ|ICR_RXCFG)) {
+               if (icr & (ICR_LSC|ICR_RXSEQ)) {
                        WM_EVCNT_INCR(&sc->sc_ev_linkintr);
                        wm_linkintr(sc, icr);
                }
@@ -7262,8 +7250,15 @@
 } while (/*CONSTCOND*/0)
 
        aprint_normal_dev(sc->sc_dev, "");
-       ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
-       ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD);
+
+       /* Only 82545 is LX */
+       if (sc->sc_type == WM_T_82545) {
+               ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
+               ADD("1000baseLX-FDX", IFM_1000_LX|IFM_FDX, ANAR_X_FD);
+       } else {
+               ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
+               ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD);
+       }
        ADD("auto", IFM_AUTO, ANAR_X_FD|ANAR_X_HD);
        aprint_normal("\n");
 
@@ -7293,7 +7288,11 @@
        }
 
        ifmr->ifm_status |= IFM_ACTIVE;
-       ifmr->ifm_active |= IFM_1000_SX;
+       /* Only 82545 is LX */
+       if (sc->sc_type == WM_T_82545)
+               ifmr->ifm_active |= IFM_1000_LX;
+       else
+               ifmr->ifm_active |= IFM_1000_SX;
        if (CSR_READ(sc, WMREG_STATUS) & STATUS_FD)
                ifmr->ifm_active |= IFM_FDX;
        else
@@ -7321,30 +7320,30 @@
        if (sc->sc_wmp->wmp_flags & WMP_F_SERDES)
                return 0;
 
-       sc->sc_txcw = 0;
-       if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
-           (sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0)
+       if ((sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_82572)
+           || (sc->sc_type >= WM_T_82575))
+               CSR_WRITE(sc, WMREG_SCTL, SCTL_DISABLE_SERDES_LOOPBACK);
+
+       /* XXX power_up_serdes_link_82575() */
+
+       sc->sc_ctrl &= ~CTRL_LRST;
+       sc->sc_txcw = TXCW_ANE;
+       if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)
+               sc->sc_txcw |= TXCW_FD | TXCW_HD;
+       else if (ife->ifm_media & IFM_FDX)
+               sc->sc_txcw |= TXCW_FD;
+       else
+               sc->sc_txcw |= TXCW_HD;
+
+       if ((sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0)
                sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE;
-       if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
-               sc->sc_txcw |= TXCW_ANE;
-       } else {
-               /*
-                * If autonegotiation is turned off, force link up and turn on
-                * full duplex
-                */
-               sc->sc_txcw &= ~TXCW_ANE;
-               sc->sc_ctrl |= CTRL_SLU | CTRL_FD;
-               sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE);
-               CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-               CSR_WRITE_FLUSH(sc);
-               delay(1000);
-       }
 
        DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n",
-                   device_xname(sc->sc_dev),sc->sc_txcw));
+                   device_xname(sc->sc_dev), sc->sc_txcw));
        CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
+       CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
        CSR_WRITE_FLUSH(sc);
-       delay(10000);
+       delay(1000);
 
        i = CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1);
        DPRINTF(WM_DEBUG_LINK,("%s: i = 0x%x\n", device_xname(sc->sc_dev),i));
@@ -7355,21 +7354,6 @@
         */
        if (((i != 0) && (sc->sc_type > WM_T_82544)) || (i == 0)) {
                /* Have signal; wait for the link to come up. */
-
-               if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
-                       /*
-                        * Reset the link, and let autonegotiation do its thing
-                        */
-                       sc->sc_ctrl |= CTRL_LRST;
-                       CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-                       CSR_WRITE_FLUSH(sc);
-                       delay(1000);
-                       sc->sc_ctrl &= ~CTRL_LRST;
-                       CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
-                       CSR_WRITE_FLUSH(sc);
-                       delay(1000);
-               }
-
                for (i = 0; i < WM_LINKUP_TIMEOUT; i++) {
                        delay(10000);
                        if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU)
@@ -7458,7 +7442,6 @@
 static void
 wm_tbi_check_link(struct wm_softc *sc)
 {
-       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
        uint32_t status;
 
@@ -7492,15 +7475,7 @@
        if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP)
            && ((status & STATUS_LU) == 0)) {
                sc->sc_tbi_linkup = 0;
-               if (sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg > 100) {
-                       /* RXCFG storm! */
-                       DPRINTF(WM_DEBUG_LINK, ("RXCFG storm! (%d)\n",
-                               sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg));
-                       wm_init_locked(ifp);
-                       WM_TX_UNLOCK(sc);
-                       ifp->if_start(ifp);
-                       WM_TX_LOCK(sc);
-               } else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+               if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
                        /* If the timer expired, retry autonegotiation */
                        if (++sc->sc_tbi_ticks >= sc->sc_tbi_anegticks) {
                                DPRINTF(WM_DEBUG_LINK, ("EXPIRE\n"));
diff -r 5c47728889ee -r 848656703229 sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h    Thu Jul 31 03:39:35 2014 +0000
+++ b/sys/dev/pci/if_wmreg.h    Thu Jul 31 03:50:09 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wmreg.h,v 1.59 2014/07/25 18:28:03 msaitoh Exp $    */
+/*     $NetBSD: if_wmreg.h,v 1.60 2014/07/31 03:50:09 msaitoh Exp $    */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -348,6 +348,7 @@
 #define SCTL_CTL_DATA_MASK 0x000000ff
 #define SCTL_CTL_ADDR_SHIFT 8
 #define SCTL_CTL_POLL_TIMEOUT 640
+#define SCTL_DISABLE_SERDES_LOOPBACK 0x0400
 
 #define        WMREG_FCAL      0x0028  /* Flow Control Address Low */
 #define        FCAL_CONST      0x00c28001      /* Flow Control MAC addr low */
@@ -540,6 +541,8 @@
 
 #define        WMREG_TXCW      0x0178  /* Transmit Configuration Word (TBI mode) */
        /* See MII ANAR_X bits. */
+#define        TXCW_FD         (1U << 5)       /* Full Duplex */
+#define        TXCW_HD         (1U << 6)       /* Half Duplex */
 #define        TXCW_SYM_PAUSE  (1U << 7)       /* sym pause request */
 #define        TXCW_ASYM_PAUSE (1U << 8)       /* asym pause request */
 #define        TXCW_TxConfig   (1U << 30)      /* Tx Config */



Home | Main Index | Thread Index | Old Index