Module Name: src
Committed By: msaitoh
Date: Wed Dec 11 10:28:19 UTC 2019
Modified Files:
src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.654 -r1.655 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.117 -r1.118 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.44 -r1.45 src/sys/dev/pci/if_wmvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.654 src/sys/dev/pci/if_wm.c:1.655
--- src/sys/dev/pci/if_wm.c:1.654 Wed Dec 11 09:48:16 2019
+++ src/sys/dev/pci/if_wm.c Wed Dec 11 10:28:19 2019
@@ -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 @@ struct wm_softc {
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 @@ alloc_retry:
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 @@ alloc_retry:
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 @@ alloc_retry:
== 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 @@ alloc_retry:
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 @@ wm_init_locked(struct ifnet *ifp)
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 @@ wm_init_locked(struct ifnet *ifp)
/* 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 @@ wm_init_locked(struct ifnet *ifp)
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_intr_legacy(void *arg)
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_linkintr_msix(void *arg)
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 @@ do { \
/* 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 @@ wm_serdes_power_up_link_82575(struct wm_
&& ((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 @@ wm_serdes_mediachange(struct ifnet *ifp)
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 @@ wm_serdes_mediachange(struct ifnet *ifp)
}
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 @@ wm_sfp_get_media_type(struct wm_softc *s
"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 @@ wm_sfp_get_media_type(struct wm_softc *s
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 @@ wm_sfp_get_media_type(struct wm_softc *s
} 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:
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.117 src/sys/dev/pci/if_wmreg.h:1.118
--- src/sys/dev/pci/if_wmreg.h:1.117 Wed Dec 11 09:48:16 2019
+++ src/sys/dev/pci/if_wmreg.h Wed Dec 11 10:28:19 2019
@@ -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 @@ struct livengood_tcpip_ctxdesc {
#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 @@ struct livengood_tcpip_ctxdesc {
#define NVM_CFG2_MNGM_NCSI 1
#define NVM_CFG2_MNGM_PT 2
+#define NVM_COMPAT_MAS_EN(x) __BIT(x) /* Media Auto Sense Enable */
#define NVM_COMPAT_SERDES_FORCE_MODE __BIT(14) /* Don't use autonego */
#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM 0x0040
Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.44 src/sys/dev/pci/if_wmvar.h:1.45
--- src/sys/dev/pci/if_wmvar.h:1.44 Tue Feb 19 07:59:17 2019
+++ src/sys/dev/pci/if_wmvar.h Wed Dec 11 10:28:19 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmvar.h,v 1.44 2019/02/19 07:59:17 msaitoh Exp $ */
+/* $NetBSD: if_wmvar.h,v 1.45 2019/12/11 10:28:19 msaitoh Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -97,6 +97,8 @@
#define WM_F_PCS_DIS_AUTONEGO 0x02000000 /* PCS Disable Autonego */
#define WM_F_PLL_WA_I210 0x04000000 /* I21[01] PLL workaround */
#define WM_F_WA_I210_CLSEM 0x08000000 /* I21[01] Semaphore workaround */
+#define WM_F_SFP 0x10000000 /* SFP */
+#define WM_F_MAS 0x20000000 /* Media Auto Sense */
#define WM_FLAGS "\20" \
"\1" "HAS_MII" "\2" "LOCK_EECD" "\3" "_B02" "\4" "_B03" \
@@ -105,7 +107,8 @@
"\15" "PCIX" "\16" "CSA" "\17" "PCIE" "\20" "SGMII" \
"\21" "NEWQUEUE" "\22" "ASF_FIRM" "\23" "ARC_SUBSYS" "\24" "AMT" \
"\25" "MANAGE" "\26" "WOL" "\27" "EEE" "\30" "ATTACHED" \
- "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\34" "CLSEMWA"
+ "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\34" "CLSEMWA" \
+ "\35" "SFP" "\36" "MAS"
/*
* Variations of Intel gigabit Ethernet controller: