Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add SFP support part 1. The code for SerDes and ...



details:   https://anonhg.NetBSD.org/src/rev/8be206d64dc0
branches:  trunk
changeset: 1005524:8be206d64dc0
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Wed Dec 11 10:28:19 2019 +0000

description:
Add SFP support part 1. The code for SerDes and SGMII setting is not include
in this commit. SFP module removal interrupt detects but not used yet:
- Detect SFP's 1000BASE-SX, 1000BASE-LX, 100BASE-FX and 1000BASE-T correctly.
- Detect the Media Auto Sense feature. Not supported yet.
- Add comment.

diffstat:

 sys/dev/pci/if_wm.c    |  111 +++++++++++++++++++++++++++++++++++++++---------
 sys/dev/pci/if_wmreg.h |    5 +-
 sys/dev/pci/if_wmvar.h |    7 ++-
 3 files changed, 98 insertions(+), 25 deletions(-)

diffs (truncated from 332 to 300 lines):

diff -r cc72655e1f5b -r 8be206d64dc0 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Dec 11 10:03:08 2019 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Dec 11 10:28:19 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.654 2019/12/11 09:48:16 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.655 2019/12/11 10:28:19 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.654 2019/12/11 09:48:16 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.655 2019/12/11 10:28:19 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -507,6 +507,7 @@
        wm_chip_type sc_type;           /* MAC type */
        int sc_rev;                     /* MAC revision */
        wm_phy_type sc_phytype;         /* PHY type */
+       uint8_t sc_sfptype;             /* SFP type */
        uint32_t sc_mediatype;          /* Media type (Copper, Fiber, SERDES)*/
 #define        WM_MEDIATYPE_UNKNOWN            0x00
 #define        WM_MEDIATYPE_FIBER              0x01
@@ -2604,11 +2605,20 @@
                break;
        }
 
-       if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
-               /* Check NVM for autonegotiation */
+       if (sc->sc_type >= WM_T_82575) {
                if (wm_nvm_read(sc, NVM_OFF_COMPAT, 1, &nvmword) == 0) {
-                       if ((nvmword & NVM_COMPAT_SERDES_FORCE_MODE) != 0)
-                               sc->sc_flags |= WM_F_PCS_DIS_AUTONEGO;
+                       if ((sc->sc_type == WM_T_82575) ||
+                           (sc->sc_type == WM_T_82576)) {
+                               /* Check NVM for autonegotiation */
+                               if ((nvmword & NVM_COMPAT_SERDES_FORCE_MODE)
+                                   != 0)
+                                       sc->sc_flags |= WM_F_PCS_DIS_AUTONEGO;
+                       }
+                       if ((sc->sc_type == WM_T_82575) ||
+                           (sc->sc_type == WM_T_I350)) {
+                               if (nvmword & NVM_COMPAT_MAS_EN(sc->sc_funcid))
+                                       sc->sc_flags |= WM_F_MAS;
+                       }
                }
        }
 
@@ -2716,12 +2726,12 @@
                link_mode = reg & CTRL_EXT_LINK_MODE_MASK;
                switch (link_mode) {
                case CTRL_EXT_LINK_MODE_1000KX:
-                       aprint_verbose_dev(sc->sc_dev, "1000KX\n");
+                       aprint_normal_dev(sc->sc_dev, "1000KX\n");
                        sc->sc_mediatype = WM_MEDIATYPE_SERDES;
                        break;
                case CTRL_EXT_LINK_MODE_SGMII:
                        if (wm_sgmii_uses_mdio(sc)) {
-                               aprint_verbose_dev(sc->sc_dev,
+                               aprint_normal_dev(sc->sc_dev,
                                    "SGMII(MDIO)\n");
                                sc->sc_flags |= WM_F_SGMII;
                                sc->sc_mediatype = WM_MEDIATYPE_COPPER;
@@ -2736,6 +2746,8 @@
                                    == CTRL_EXT_LINK_MODE_SGMII) {
                                        sc->sc_mediatype = WM_MEDIATYPE_COPPER;
                                        sc->sc_flags |= WM_F_SGMII;
+                                       aprint_verbose_dev(sc->sc_dev,
+                                           "SGMII\n");
                                } else {
                                        sc->sc_mediatype = WM_MEDIATYPE_SERDES;
                                        aprint_verbose_dev(sc->sc_dev,
@@ -2744,25 +2756,26 @@
                                break;
                        }
                        if (sc->sc_mediatype == WM_MEDIATYPE_SERDES)
-                               aprint_verbose_dev(sc->sc_dev, "SERDES\n");
+                               aprint_normal_dev(sc->sc_dev, "SERDES(SFP)\n");
+                       else if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) {
+                               aprint_normal_dev(sc->sc_dev, "SGMII(SFP)\n");
+                               sc->sc_flags |= WM_F_SGMII;
+                       }
+                       /* Do not change link mode for 100BaseFX */
+                       if (sc->sc_sfptype == SFF_SFP_ETH_FLAGS_100FX)
+                               break;
 
                        /* Change current link mode setting */
                        reg &= ~CTRL_EXT_LINK_MODE_MASK;
-                       switch (sc->sc_mediatype) {
-                       case WM_MEDIATYPE_COPPER:
+                       if (sc->sc_mediatype == WM_MEDIATYPE_COPPER)
                                reg |= CTRL_EXT_LINK_MODE_SGMII;
-                               break;
-                       case WM_MEDIATYPE_SERDES:
+                       else
                                reg |= CTRL_EXT_LINK_MODE_PCIE_SERDES;
-                               break;
-                       default:
-                               break;
-                       }
                        CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
                        break;
                case CTRL_EXT_LINK_MODE_GMII:
                default:
-                       aprint_verbose_dev(sc->sc_dev, "Copper\n");
+                       aprint_normal_dev(sc->sc_dev, "Copper\n");
                        sc->sc_mediatype = WM_MEDIATYPE_COPPER;
                        break;
                }
@@ -5695,7 +5708,7 @@
        struct wm_softc *sc = ifp->if_softc;
        struct ethercom *ec = &sc->sc_ethercom;
        int i, j, trynum, error = 0;
-       uint32_t reg;
+       uint32_t reg, sfp_mask = 0;
 
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
@@ -6047,6 +6060,13 @@
        /* Set up the interrupt registers. */
        CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
 
+       /* Enable SFP module insertion interrupt if it's required */
+       if ((sc->sc_flags & WM_F_SFP) != 0) {
+               sc->sc_ctrl |= CTRL_EXTLINK_EN;
+               CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+               sfp_mask = ICR_GPI(0);
+       }
+
        if (wm_is_using_msix(sc)) {
                uint32_t mask;
                struct wm_queue *wmq;
@@ -6083,12 +6103,14 @@
                        CSR_WRITE(sc, WMREG_EIAC, mask);
                        CSR_WRITE(sc, WMREG_EIAM, mask);
                        CSR_WRITE(sc, WMREG_EIMS, mask);
-                       CSR_WRITE(sc, WMREG_IMS, ICR_LSC);
+
+                       /* For other interrupts */
+                       CSR_WRITE(sc, WMREG_IMS, ICR_LSC | sfp_mask);
                        break;
                }
        } else {
                sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
-                   ICR_RXO | ICR_RXT0;
+                   ICR_RXO | ICR_RXT0 | sfp_mask;
                CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
        }
 
@@ -9456,6 +9478,8 @@
                        WM_EVCNT_INCR(&sc->sc_ev_linkintr);
                        wm_linkintr(sc, icr);
                }
+               if ((icr & ICR_GPI(0)) != 0)
+                       device_printf(sc->sc_dev, "got module interrupt\n");
 
                WM_CORE_UNLOCK(sc);
 
@@ -9643,6 +9667,8 @@
                WM_EVCNT_INCR(&sc->sc_ev_linkintr);
                wm_linkintr(sc, ICR_LSC);
        }
+       if ((reg & ICR_GPI(0)) != 0)
+               device_printf(sc->sc_dev, "got module interrupt\n");
 
        /*
         * XXX 82574 MSI-X mode workaround
@@ -11804,6 +11830,31 @@
                /* Only 82545 is LX (XXX except SFP) */
                ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
                ADD("1000baseLX-FDX", IFM_1000_LX | IFM_FDX, ANAR_X_FD);
+       } else if (sc->sc_sfptype != 0) {
+               /* XXX wm(4) fiber/serdes don't use ifm_data */
+               switch (sc->sc_sfptype) {
+               default:
+               case SFF_SFP_ETH_FLAGS_1000SX:
+                       ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
+                       ADD("1000baseSX-FDX", IFM_1000_SX | IFM_FDX, ANAR_X_FD);
+                       break;
+               case SFF_SFP_ETH_FLAGS_1000LX:
+                       ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
+                       ADD("1000baseLX-FDX", IFM_1000_LX | IFM_FDX, ANAR_X_FD);
+                       break;
+               case SFF_SFP_ETH_FLAGS_1000CX:
+                       ADD("1000baseCX", IFM_1000_CX, ANAR_X_HD);
+                       ADD("1000baseCX-FDX", IFM_1000_CX | IFM_FDX, ANAR_X_FD);
+                       break;
+               case SFF_SFP_ETH_FLAGS_1000T:
+                       ADD("1000baseT", IFM_1000_T, 0);
+                       ADD("1000baseT-FDX", IFM_1000_T | IFM_FDX, 0);
+                       break;
+               case SFF_SFP_ETH_FLAGS_100FX:
+                       ADD("100baseFX", IFM_100_FX, ANAR_TX);
+                       ADD("100baseFX-FDX", IFM_100_FX | IFM_FDX, ANAR_TX_FD);
+                       break;
+               }
        } else {
                ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
                ADD("1000baseSX-FDX", IFM_1000_SX | IFM_FDX, ANAR_X_FD);
@@ -12122,13 +12173,17 @@
            && ((sc->sc_flags & WM_F_SGMII) == 0))
                return;
 
+       /* Enable PCS to turn on link */
        reg = CSR_READ(sc, WMREG_PCS_CFG);
        reg |= PCS_CFG_PCS_EN;
        CSR_WRITE(sc, WMREG_PCS_CFG, reg);
 
+       /* Power up the laser */
        reg = CSR_READ(sc, WMREG_CTRL_EXT);
        reg &= ~CTRL_EXT_SWDPIN(3);
        CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+
+       /* Flush the write to verify completion */
        CSR_WRITE_FLUSH(sc);
 }
 
@@ -12155,7 +12210,9 @@
        pcs_lctl = CSR_READ(sc, WMREG_PCS_LCTL);
        switch (ctrl_ext & CTRL_EXT_LINK_MODE_MASK) {
        case CTRL_EXT_LINK_MODE_SGMII:
+               /* SGMII mode lets the phy handle forcing speed/duplex */
                pcs_autoneg = true;
+               /* Autoneg time out should be disabled for SGMII mode */
                pcs_lctl &= ~PCS_LCTL_AN_TIMEOUT;
                break;
        case CTRL_EXT_LINK_MODE_1000KX:
@@ -12169,14 +12226,20 @@
                }
                sc->sc_ctrl |= CTRL_SPEED_1000 | CTRL_FRCSPD | CTRL_FD
                    | CTRL_FRCFDX;
+
+               /* Set speed of 1000/Full if speed/duplex is forced */
                pcs_lctl |= PCS_LCTL_FSV_1000 | PCS_LCTL_FDV_FULL;
        }
        CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
 
        if (pcs_autoneg) {
+               /* Set PCS register for autoneg */
                pcs_lctl |= PCS_LCTL_AN_ENABLE | PCS_LCTL_AN_RESTART;
+
+               /* Disable force flow control for autoneg */
                pcs_lctl &= ~PCS_LCTL_FORCE_FC;
 
+               /* Configure flow control advertisement for autoneg */
                reg = CSR_READ(sc, WMREG_PCS_ANADV);
                reg &= ~(TXCW_ASYM_PAUSE | TXCW_SYM_PAUSE);
                reg |= TXCW_ASYM_PAUSE | TXCW_SYM_PAUSE;
@@ -12383,6 +12446,7 @@
                    "Module/Connector soldered to board\n");
                break;
        case SFF_SFP_ID_SFP:
+               sc->sc_flags |= WM_F_SFP;
                aprint_normal_dev(sc->sc_dev, "SFP\n");
                break;
        case SFF_SFP_ID_UNKNOWN:
@@ -12395,6 +12459,7 @@
        if (rv != 0)
                goto out;
 
+       sc->sc_sfptype = val;
        if ((val & (SFF_SFP_ETH_FLAGS_1000SX | SFF_SFP_ETH_FLAGS_1000LX)) != 0)
                mediatype = WM_MEDIATYPE_SERDES;
        else if ((val & SFF_SFP_ETH_FLAGS_1000T) != 0) {
@@ -12403,6 +12468,10 @@
        } else if ((val & SFF_SFP_ETH_FLAGS_100FX) != 0) {
                sc->sc_flags |= WM_F_SGMII;
                mediatype = WM_MEDIATYPE_SERDES;
+       } else {
+               device_printf(sc->sc_dev, "%s: unknown media type? (0x%hhx)\n",
+                   __func__, sc->sc_sfptype);
+               sc->sc_sfptype = 0; /* XXX unknown */
        }
 
 out:
diff -r cc72655e1f5b -r 8be206d64dc0 sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h    Wed Dec 11 10:03:08 2019 +0000
+++ b/sys/dev/pci/if_wmreg.h    Wed Dec 11 10:28:19 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wmreg.h,v 1.117 2019/12/11 09:48:16 msaitoh Exp $   */
+/*     $NetBSD: if_wmreg.h,v 1.118 2019/12/11 10:28:19 msaitoh Exp $   */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -694,7 +694,7 @@
 #define        ICR_RXT0        (1U << 7)       /* Rx ring 0 timer */
 #define        ICR_MDAC        (1U << 9)       /* MDIO access complete */
 #define        ICR_RXCFG       (1U << 10)      /* Receiving /C/ */
-#define        ICR_GPI(x)      (1U << (x))     /* general purpose interrupts */
+#define        ICR_GPI(x)      __BIT(11+(x))   /* general purpose interrupts */
 #define        ICR_RXQ(x)      __BIT(20+(x))   /* 82574: Rx queue x interrupt x=0,1 */
 #define        ICR_TXQ(x)      __BIT(22+(x))   /* 82574: Tx queue x interrupt x=0,1 */
 #define        ICR_OTHER       __BIT(24)       /* 82574: Other interrupt */
@@ -1475,6 +1475,7 @@
 #define        NVM_CFG2_MNGM_NCSI      1
 #define        NVM_CFG2_MNGM_PT        2
 



Home | Main Index | Thread Index | Old Index