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 two bugs for non-SERDES fiber. Tested on 825...



details:   https://anonhg.NetBSD.org/src/rev/c8010643ec8b
branches:  trunk
changeset: 365255:c8010643ec8b
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Aug 09 16:27:23 2018 +0000

description:
Fix two bugs for non-SERDES fiber. Tested on 82544EI(0x1009), 82545GM(0x1027),
82546GB(0x107a), 82571GB(0x105f), 82572EI(0x107e). Tested on SERDES
82580(0x150e (Winyao SERDES SFP)) and 82580(0x150e) as regression test:

- Fix a bug that the link can't detect in link interrupt function for
  non-SERDES fiber. When the signal is detected & STATUS_LU == 0 & RXCW == 0,
  it's required to set CTRL_SLU and CTRL_FD bit. wm_check_for_link() is the
  function to do it. If a link status change interrupt occured, call
  wm_check_for_link() before checking current link staus.
- Fix a bug that 82542 misunderstand fiber's signal detection. CTRL_SWDPIN(1)
  is used for fiber's signal and it's value is reversed only on 82543 and
  82544. Simplify the code and move it into a new function wm_tbi_havesignal()
  and use it.

diffstat:

 sys/dev/pci/if_wm.c |  78 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 50 insertions(+), 28 deletions(-)

diffs (162 lines):

diff -r 1af1d9f963aa -r c8010643ec8b sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Aug 09 13:49:30 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Aug 09 16:27:23 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.583 2018/06/26 06:48:01 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.584 2018/08/09 16:27:23 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.583 2018/06/26 06:48:01 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.584 2018/08/09 16:27:23 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -842,6 +842,7 @@
 static int     wm_sgmii_readreg(device_t, int, int);
 static void    wm_sgmii_writereg(device_t, int, int, int);
 /* TBI related */
+static bool    wm_tbi_havesignal(struct wm_softc *, uint32_t);
 static void    wm_tbi_mediainit(struct wm_softc *);
 static int     wm_tbi_mediachange(struct ifnet *);
 static void    wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *);
@@ -8755,6 +8756,7 @@
 
        status = CSR_READ(sc, WMREG_STATUS);
        if (icr & ICR_LSC) {
+               wm_check_for_link(sc);
                if (status & STATUS_LU) {
                        DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n",
                                device_xname(sc->sc_dev),
@@ -10962,6 +10964,23 @@
 
 /* TBI related */
 
+static bool
+wm_tbi_havesignal(struct wm_softc *sc, uint32_t ctrl)
+{
+       bool sig;
+
+       sig = ctrl & CTRL_SWDPIN(1);
+
+       /*
+        * On 82543 and 82544, the CTRL_SWDPIN(1) bit will be 0 if the optics
+        * detect a signal, 1 if they don't.
+        */
+       if ((sc->sc_type == WM_T_82543) || (sc->sc_type == WM_T_82544))
+               sig = !sig;
+
+       return sig;
+}
+
 /*
  * wm_tbi_mediainit:
  *
@@ -11053,9 +11072,11 @@
 {
        struct wm_softc *sc = ifp->if_softc;
        struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
-       uint32_t status;
+       uint32_t status, ctrl;
+       bool signal;
        int i;
 
+       KASSERT(sc->sc_mediatype != WM_MEDIATYPE_COPPER);
        if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) {
                /* XXX need some work for >= 82571 and < 82575 */
                if (sc->sc_type < WM_T_82575)
@@ -11085,14 +11106,13 @@
        CSR_WRITE_FLUSH(sc);
        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));
-
-       /*
-        * On 82544 chips and later, the CTRL_SWDPIN(1) bit will be set if the
-        * optics detect a signal, 0 if they don't.
-        */
-       if (((i != 0) && (sc->sc_type > WM_T_82544)) || (i == 0)) {
+       ctrl =  CSR_READ(sc, WMREG_CTRL);
+       signal = wm_tbi_havesignal(sc, ctrl);
+
+       DPRINTF(WM_DEBUG_LINK, ("%s: signal = %d\n", device_xname(sc->sc_dev),
+               signal));
+
+       if (signal) {
                /* Have signal; wait for the link to come up. */
                for (i = 0; i < WM_LINKUP_TIMEOUT; i++) {
                        delay(10000);
@@ -11198,7 +11218,10 @@
        uint32_t rxcw;
        uint32_t ctrl;
        uint32_t status;
-       uint32_t sig;
+       bool signal;
+
+       DPRINTF(WM_DEBUG_LINK, ("%s: %s called\n",
+               device_xname(sc->sc_dev), __func__));
 
        if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) {
                /* XXX need some work for >= 82571 */
@@ -11211,13 +11234,11 @@
        rxcw = CSR_READ(sc, WMREG_RXCW);
        ctrl = CSR_READ(sc, WMREG_CTRL);
        status = CSR_READ(sc, WMREG_STATUS);
-
-       sig = (sc->sc_type > WM_T_82544) ? CTRL_SWDPIN(1) : 0;
-
+       signal = wm_tbi_havesignal(sc, ctrl);
+       
        DPRINTF(WM_DEBUG_LINK,
-           ("%s: %s: sig = %d, status_lu = %d, rxcw_c = %d\n",
-               device_xname(sc->sc_dev), __func__,
-               ((ctrl & CTRL_SWDPIN(1)) == sig),
+           ("%s: %s: signal = %d, status_lu = %d, rxcw_c = %d\n",
+               device_xname(sc->sc_dev), __func__, signal,
                ((status & STATUS_LU) != 0), ((rxcw & RXCW_C) != 0)));
 
        /*
@@ -11232,11 +11253,10 @@
         *      1    1    1     If IFM_AUTO, back to autonego
         *
         */
-       if (((ctrl & CTRL_SWDPIN(1)) == sig)
-           && ((status & STATUS_LU) == 0)
-           && ((rxcw & RXCW_C) == 0)) {
-               DPRINTF(WM_DEBUG_LINK, ("%s: force linkup and fullduplex\n",
-                       __func__));
+       if (signal && ((status & STATUS_LU) == 0) && ((rxcw & RXCW_C) == 0)) {
+               DPRINTF(WM_DEBUG_LINK,
+                   ("%s: %s: force linkup and fullduplex\n",
+                       device_xname(sc->sc_dev), __func__));
                sc->sc_tbi_linkup = 0;
                /* Disable auto-negotiation in the TXCW register */
                CSR_WRITE(sc, WMREG_TXCW, (sc->sc_txcw & ~TXCW_ANE));
@@ -11253,15 +11273,17 @@
            && ((rxcw & RXCW_C) != 0)
            && (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)) {
                sc->sc_tbi_linkup = 1;
-               DPRINTF(WM_DEBUG_LINK, ("%s: go back to autonego\n",
+               DPRINTF(WM_DEBUG_LINK, ("%s: %s: go back to autonego\n",
+                       device_xname(sc->sc_dev),
                        __func__));
                CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
                CSR_WRITE(sc, WMREG_CTRL, (ctrl & ~CTRL_SLU));
-       } else if (((ctrl & CTRL_SWDPIN(1)) == sig)
-           && ((rxcw & RXCW_C) != 0)) {
-               DPRINTF(WM_DEBUG_LINK, ("/C/"));
+       } else if (signal && ((rxcw & RXCW_C) != 0)) {
+               DPRINTF(WM_DEBUG_LINK, ("%s: %s: /C/",
+                       device_xname(sc->sc_dev), __func__));
        } else {
-               DPRINTF(WM_DEBUG_LINK, ("%s: %x,%x,%x\n", __func__, rxcw, ctrl,
+               DPRINTF(WM_DEBUG_LINK, ("%s: %s: linkup %08x,%08x,%08x\n",
+                       device_xname(sc->sc_dev), __func__, rxcw, ctrl,
                        status));
        }
 



Home | Main Index | Thread Index | Old Index