Module Name: src Committed By: msaitoh Date: Tue Dec 13 10:01:44 UTC 2016
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h Log Message: - Change to use 2500Base-KX correctly on C2000(I354). It worked, but the output of ifconfig and if_baudrate was not good. Tested by nils@: - The STATUS_TBIMODE bit in the STATUS register is deleted since 82575, so check for 82575 and newer first and then check for old devices. - Check the 2P5_SKU and 2P5_SKU_OVER bit for KX. - Set IFM_2500_SX instead of IFM_1000_SX for 2.5G. - Check SERDES's speed directly from the PCS layer (PCS_LSTS register) for old devices. - Style fix. To generate a diff of this commit: cvs rdiff -u -r1.456 -r1.457 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.93 -r1.94 src/sys/dev/pci/if_wmreg.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.456 src/sys/dev/pci/if_wm.c:1.457 --- src/sys/dev/pci/if_wm.c:1.456 Thu Dec 8 01:12:01 2016 +++ src/sys/dev/pci/if_wm.c Tue Dec 13 10:01:44 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.456 2016/12/08 01:12:01 ozaki-r Exp $ */ +/* $NetBSD: if_wm.c,v 1.457 2016/12/13 10:01:44 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.456 2016/12/08 01:12:01 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.457 2016/12/13 10:01:44 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -2411,100 +2411,91 @@ alloc_retry: || sc->sc_type == WM_T_82574 || sc->sc_type == WM_T_82583) { /* STATUS_TBIMODE reserved/reused, can't rely on it */ wm_gmii_mediainit(sc, wmp->wmp_product); - } else if (sc->sc_type < WM_T_82543 || - (CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) { - if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) { - aprint_error_dev(sc->sc_dev, - "WARNING: TBIMODE set on 1000BASE-T product!\n"); - sc->sc_mediatype = WM_MEDIATYPE_FIBER; - } - wm_tbi_mediainit(sc); - } else { - switch (sc->sc_type) { - case WM_T_82575: - case WM_T_82576: - case WM_T_82580: - case WM_T_I350: - case WM_T_I354: - case WM_T_I210: - case WM_T_I211: - reg = CSR_READ(sc, WMREG_CTRL_EXT); - 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"); - sc->sc_mediatype = WM_MEDIATYPE_SERDES; + } else if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576) + || (sc->sc_type ==WM_T_82580) || (sc->sc_type ==WM_T_I350) + || (sc->sc_type ==WM_T_I354) || (sc->sc_type ==WM_T_I210) + || (sc->sc_type ==WM_T_I211)) { + reg = CSR_READ(sc, WMREG_CTRL_EXT); + 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"); + 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, + "SGMII(MDIO)\n"); + sc->sc_flags |= WM_F_SGMII; + sc->sc_mediatype = WM_MEDIATYPE_COPPER; break; - case CTRL_EXT_LINK_MODE_SGMII: - if (wm_sgmii_uses_mdio(sc)) { - aprint_verbose_dev(sc->sc_dev, - "SGMII(MDIO)\n"); - sc->sc_flags |= WM_F_SGMII; + } + aprint_verbose_dev(sc->sc_dev, "SGMII(I2C)\n"); + /*FALLTHROUGH*/ + case CTRL_EXT_LINK_MODE_PCIE_SERDES: + sc->sc_mediatype = wm_sfp_get_media_type(sc); + if (sc->sc_mediatype == WM_MEDIATYPE_UNKNOWN) { + if (link_mode + == CTRL_EXT_LINK_MODE_SGMII) { sc->sc_mediatype = WM_MEDIATYPE_COPPER; - break; - } - aprint_verbose_dev(sc->sc_dev, "SGMII(I2C)\n"); - /*FALLTHROUGH*/ - case CTRL_EXT_LINK_MODE_PCIE_SERDES: - sc->sc_mediatype = wm_sfp_get_media_type(sc); - if (sc->sc_mediatype == WM_MEDIATYPE_UNKNOWN) { - if (link_mode - == CTRL_EXT_LINK_MODE_SGMII) { - sc->sc_mediatype - = WM_MEDIATYPE_COPPER; - sc->sc_flags |= WM_F_SGMII; - } else { - sc->sc_mediatype - = WM_MEDIATYPE_SERDES; - aprint_verbose_dev(sc->sc_dev, - "SERDES\n"); - } - break; - } - if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) + sc->sc_flags |= WM_F_SGMII; + } else { + sc->sc_mediatype = WM_MEDIATYPE_SERDES; aprint_verbose_dev(sc->sc_dev, "SERDES\n"); - - /* Change current link mode setting */ - reg &= ~CTRL_EXT_LINK_MODE_MASK; - switch (sc->sc_mediatype) { - case WM_MEDIATYPE_COPPER: - reg |= CTRL_EXT_LINK_MODE_SGMII; - break; - case WM_MEDIATYPE_SERDES: - reg |= CTRL_EXT_LINK_MODE_PCIE_SERDES; - break; - default: - break; } - CSR_WRITE(sc, WMREG_CTRL_EXT, reg); break; - case CTRL_EXT_LINK_MODE_GMII: + } + if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) + aprint_verbose_dev(sc->sc_dev, "SERDES\n"); + + /* Change current link mode setting */ + reg &= ~CTRL_EXT_LINK_MODE_MASK; + switch (sc->sc_mediatype) { + case WM_MEDIATYPE_COPPER: + reg |= CTRL_EXT_LINK_MODE_SGMII; + break; + case WM_MEDIATYPE_SERDES: + reg |= CTRL_EXT_LINK_MODE_PCIE_SERDES; + break; default: - aprint_verbose_dev(sc->sc_dev, "Copper\n"); - sc->sc_mediatype = WM_MEDIATYPE_COPPER; break; } - - reg &= ~CTRL_EXT_I2C_ENA; - if ((sc->sc_flags & WM_F_SGMII) != 0) - reg |= CTRL_EXT_I2C_ENA; - else - reg &= ~CTRL_EXT_I2C_ENA; CSR_WRITE(sc, WMREG_CTRL_EXT, reg); - - if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) - wm_gmii_mediainit(sc, wmp->wmp_product); - else - wm_tbi_mediainit(sc); break; + case CTRL_EXT_LINK_MODE_GMII: default: - if (sc->sc_mediatype == WM_MEDIATYPE_FIBER) - aprint_error_dev(sc->sc_dev, - "WARNING: TBIMODE clear on 1000BASE-X product!\n"); + aprint_verbose_dev(sc->sc_dev, "Copper\n"); sc->sc_mediatype = WM_MEDIATYPE_COPPER; + break; + } + + reg &= ~CTRL_EXT_I2C_ENA; + if ((sc->sc_flags & WM_F_SGMII) != 0) + reg |= CTRL_EXT_I2C_ENA; + else + reg &= ~CTRL_EXT_I2C_ENA; + CSR_WRITE(sc, WMREG_CTRL_EXT, reg); + + if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) wm_gmii_mediainit(sc, wmp->wmp_product); + else + wm_tbi_mediainit(sc); + } else if (sc->sc_type < WM_T_82543 || + (CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) { + if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) { + aprint_error_dev(sc->sc_dev, + "WARNING: TBIMODE set on 1000BASE-T product!\n"); + sc->sc_mediatype = WM_MEDIATYPE_FIBER; + } + wm_tbi_mediainit(sc); + } else { + if (sc->sc_mediatype == WM_MEDIATYPE_FIBER) { + aprint_error_dev(sc->sc_dev, + "WARNING: TBIMODE clear on 1000BASE-X product!\n"); + sc->sc_mediatype = WM_MEDIATYPE_COPPER; } + wm_gmii_mediainit(sc, wmp->wmp_product); } ifp = &sc->sc_ethercom.ec_if; @@ -9677,8 +9668,17 @@ do { \ aprint_normal_dev(sc->sc_dev, ""); - /* Only 82545 is LX */ - if (sc->sc_type == WM_T_82545) { + if (sc->sc_type == WM_T_I354) { + uint32_t status; + + status = CSR_READ(sc, WMREG_STATUS); + if (((status & STATUS_2P5_SKU) != 0) + && ((status & STATUS_2P5_SKU_OVER) == 0)) { + ADD("2500baseKX-FDX", IFM_2500_SX | IFM_FDX,ANAR_X_FD); + } else + ADD("1000baseSX-FDX", IFM_1000_SX | IFM_FDX,ANAR_X_FD); + } else if (sc->sc_type == WM_T_82545) { + /* 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 { @@ -10087,7 +10087,32 @@ wm_serdes_mediastatus(struct ifnet *ifp, sc->sc_tbi_linkup = 1; ifmr->ifm_status |= IFM_ACTIVE; - ifmr->ifm_active |= IFM_1000_SX; /* XXX */ + if (sc->sc_type == WM_T_I354) { + uint32_t status; + + status = CSR_READ(sc, WMREG_STATUS); + if (((status & STATUS_2P5_SKU) != 0) + && ((status & STATUS_2P5_SKU_OVER) == 0)) { + ifmr->ifm_active |= IFM_2500_SX; /* XXX KX */ + } else + ifmr->ifm_active |= IFM_1000_SX; /* XXX KX */ + } else { + switch (__SHIFTOUT(reg, PCS_LSTS_SPEED)) { + case PCS_LSTS_SPEED_10: + ifmr->ifm_active |= IFM_10_T; /* XXX */ + break; + case PCS_LSTS_SPEED_100: + ifmr->ifm_active |= IFM_100_FX; /* XXX */ + break; + case PCS_LSTS_SPEED_1000: + ifmr->ifm_active |= IFM_1000_SX; /* XXX */ + break; + default: + device_printf(sc->sc_dev, "Unknown speed\n"); + ifmr->ifm_active |= IFM_1000_SX; /* XXX */ + break; + } + } if ((reg & PCS_LSTS_FDX) != 0) ifmr->ifm_active |= IFM_FDX; else @@ -10120,7 +10145,6 @@ wm_serdes_mediastatus(struct ifnet *ifp, && (pcs_lpab & TXCW_ASYM_PAUSE)) { mii->mii_media_active |= IFM_FLOW | IFM_ETH_RXPAUSE; - } else { } } ifmr->ifm_active = (ifmr->ifm_active & ~IFM_ETH_FMASK) @@ -10161,7 +10185,7 @@ wm_serdes_tick(struct wm_softc *sc) } else { mii->mii_media_status |= IFM_NONE; sc->sc_tbi_linkup = 0; - /* If the timer expired, retry autonegotiation */ + /* If the timer expired, retry autonegotiation */ if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) && (++sc->sc_tbi_serdes_ticks >= sc->sc_tbi_serdes_anegticks)) { Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.93 src/sys/dev/pci/if_wmreg.h:1.94 --- src/sys/dev/pci/if_wmreg.h:1.93 Wed Nov 16 08:56:17 2016 +++ src/sys/dev/pci/if_wmreg.h Tue Dec 13 10:01:44 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.93 2016/11/16 08:56:17 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.94 2016/12/13 10:01:44 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -267,7 +267,9 @@ struct livengood_tcpip_ctxdesc { #define STATUS_PHYRA (1U << 10) /* PHY Reset Asserted (PCH) */ #define STATUS_PCI66 (1U << 11) /* 66MHz bus (Livengood) */ #define STATUS_BUS64 (1U << 12) /* 64-bit bus (Livengood) */ +#define STATUS_2P5_SKU __BIT(12) /* Value of the 2.5GBE SKU strap */ #define STATUS_PCIX_MODE (1U << 13) /* PCIX mode (Cordova) */ +#define STATUS_2P5_SKU_OVER __BIT(13) /* Value of the 2.5GBE SKU override */ #define STATUS_PCIXSPD(x) ((x) << 14) /* PCIX speed indication (Cordova) */ #define STATUS_PCIXSPD_50_66 STATUS_PCIXSPD(0) #define STATUS_PCIXSPD_66_100 STATUS_PCIXSPD(1) @@ -915,8 +917,10 @@ struct livengood_tcpip_ctxdesc { #define WMREG_PCS_LSTS 0x420c /* PCS Link Status */ #define PCS_LSTS_LINKOK __BIT(0) -#define PCS_LSTS_SPEED_100 __BIT(1) -#define PCS_LSTS_SPEED_1000 __BIT(2) +#define PCS_LSTS_SPEED __BITS(2, 1) +#define PCS_LSTS_SPEED_10 0 +#define PCS_LSTS_SPEED_100 1 +#define PCS_LSTS_SPEED_1000 2 #define PCS_LSTS_FDX __BIT(3) #define PCS_LSTS_AN_COMP __BIT(16)