Module Name: src Committed By: snj Date: Thu Mar 9 06:28:36 UTC 2017
Modified Files: src/sys/dev/pci [netbsd-7]: if_wm.c if_wmreg.h if_wmvar.h Log Message: Pull up following revision(s) (requested by msaitoh in ticket #1372): sys/dev/pci/if_wm.c: revisions 1.462, 1.464-1.465 1.474 via patch sys/dev/pci/if_wmreg.h: revision 1.97 sys/dev/pci/if_wmvar.h: revision 1.33 - Set IPV6EXDIS bit in RFCTL register because of an Errata on 82575 and newer devices. - Linux and FreeBSD defines 0x10f5 as E1000_DEV_ID_ICH9_IGP_M_AMT. In reality, This is not IGP but BM. Add new case to identify PHY type device. Fixes PR#51924 reported byJarle Greipsland. - Use new wm_gmii_setup_phytype() function to setup sc_phytype and mii_{read|write}reg. This change improves detection of PHY type. - Fix typo in comment. To generate a diff of this commit: cvs rdiff -u -r1.289.2.12 -r1.289.2.13 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.60.2.7 -r1.60.2.8 src/sys/dev/pci/if_wmreg.h cvs rdiff -u -r1.19.2.5 -r1.19.2.6 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.289.2.12 src/sys/dev/pci/if_wm.c:1.289.2.13 --- src/sys/dev/pci/if_wm.c:1.289.2.12 Sun Dec 18 07:53:08 2016 +++ src/sys/dev/pci/if_wm.c Thu Mar 9 06:28:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.289.2.12 2016/12/18 07:53:08 snj Exp $ */ +/* $NetBSD: if_wm.c,v 1.289.2.13 2017/03/09 06:28:36 snj 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.289.2.12 2016/12/18 07:53:08 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.289.2.13 2017/03/09 06:28:36 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -638,6 +638,7 @@ static int wm_intr(void *); static void wm_tbi_serdes_set_linkled(struct wm_softc *); /* GMII related */ static void wm_gmii_reset(struct wm_softc *); +static void wm_gmii_setup_phytype(struct wm_softc *sc, uint32_t, uint16_t); static int wm_get_phy_id_82575(struct wm_softc *); static void wm_gmii_mediainit(struct wm_softc *, pci_product_id_t); static int wm_gmii_mediachange(struct ifnet *); @@ -3670,11 +3671,11 @@ wm_initialize_hardware_bits(struct wm_so } CSR_WRITE(sc, WMREG_TARC0, tarc0); + switch (sc->sc_type) { /* - * 8257[12] Errata No.52 and some others. + * 8257[12] Errata No.52, 82573 Errata No.43 and some others. * Avoid RSS Hash Value bug. */ - switch (sc->sc_type) { case WM_T_82571: case WM_T_82572: case WM_T_82573: @@ -3687,6 +3688,20 @@ wm_initialize_hardware_bits(struct wm_so default: break; } + } else if ((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211)) { + /* + * 82575 Errata XXX, 82576 Errata 46, 82580 Errata 24, + * I350 Errata 37, I210 Errata No. 31 and I211 Errata No. 11: + * "Certain Malformed IPv6 Extension Headers are Not Processed + * Correctly by the Device" + * + * I354(C2000) Errata AVR53: + * "Malformed IPv6 Extension Headers May Result in LAN Device + * Hang" + */ + reg = CSR_READ(sc, WMREG_RFCTL); + reg |= WMREG_RFCTL_IPV6EXDIS; + CSR_WRITE(sc, WMREG_RFCTL, reg); } } @@ -6798,6 +6813,251 @@ wm_gmii_reset(struct wm_softc *sc) } /* + * Setup sc_phytype and mii_{read|write}reg. + * + * To identify PHY type, correct read/write function should be selected. + * To select correct read/write function, PCI ID or MAC type are required + * without accessing PHY registers. + * + * On the first call of this function, PHY ID is not known yet. Check + * PCI ID or MAC type. The list of the PCI ID may not be perfect, so the + * result might be incorrect. + * + * In the second call, PHY OUI and model is used to identify PHY type. + * It might not be perfpect because of the lack of compared entry, but it + * would be better than the first call. + * + * If the detected new result and previous assumption is different, + * diagnous message will be printed. + */ +static void +wm_gmii_setup_phytype(struct wm_softc *sc, uint32_t phy_oui, + uint16_t phy_model) +{ + device_t dev = sc->sc_dev; + struct mii_data *mii = &sc->sc_mii; + uint16_t new_phytype = WMPHY_UNKNOWN; + uint16_t doubt_phytype = WMPHY_UNKNOWN; + mii_readreg_t new_readreg; + mii_writereg_t new_writereg; + + if (mii->mii_readreg == NULL) { + /* + * This is the first call of this function. For ICH and PCH + * variants, it's difficult to determine the PHY access method + * by sc_type, so use the PCI product ID for some devices. + */ + + switch (sc->sc_pcidevid) { + case PCI_PRODUCT_INTEL_PCH_M_LM: + case PCI_PRODUCT_INTEL_PCH_M_LC: + /* 82577 */ + new_phytype = WMPHY_82577; + break; + case PCI_PRODUCT_INTEL_PCH_D_DM: + case PCI_PRODUCT_INTEL_PCH_D_DC: + /* 82578 */ + new_phytype = WMPHY_82578; + break; + case PCI_PRODUCT_INTEL_PCH2_LV_LM: + case PCI_PRODUCT_INTEL_PCH2_LV_V: + /* 82579 */ + new_phytype = WMPHY_82579; + break; + case PCI_PRODUCT_INTEL_82801H_82567V_3: + case PCI_PRODUCT_INTEL_82801I_BM: + case PCI_PRODUCT_INTEL_82801I_IGP_M_AMT: /* Not IGP but BM */ + case PCI_PRODUCT_INTEL_82801J_R_BM_LM: + case PCI_PRODUCT_INTEL_82801J_R_BM_LF: + case PCI_PRODUCT_INTEL_82801J_D_BM_LM: + case PCI_PRODUCT_INTEL_82801J_D_BM_LF: + case PCI_PRODUCT_INTEL_82801J_R_BM_V: + /* ICH8, 9, 10 with 82567 */ + new_phytype = WMPHY_BM; + break; + default: + break; + } + } else { + /* It's not the first call. Use PHY OUI and model */ + switch (phy_oui) { + case MII_OUI_ATHEROS: /* XXX ??? */ + switch (phy_model) { + case 0x0004: /* XXX */ + new_phytype = WMPHY_82578; + break; + default: + break; + } + break; + case MII_OUI_xxMARVELL: + switch (phy_model) { + case MII_MODEL_xxMARVELL_I210: + new_phytype = WMPHY_I210; + break; + case MII_MODEL_xxMARVELL_E1011: + case MII_MODEL_xxMARVELL_E1000_3: + case MII_MODEL_xxMARVELL_E1000_5: + case MII_MODEL_xxMARVELL_E1112: + new_phytype = WMPHY_M88; + break; + case MII_MODEL_xxMARVELL_E1149: + new_phytype = WMPHY_BM; + break; + case MII_MODEL_xxMARVELL_E1111: + case MII_MODEL_xxMARVELL_I347: + case MII_MODEL_xxMARVELL_E1512: + case MII_MODEL_xxMARVELL_E1340M: + case MII_MODEL_xxMARVELL_E1543: + new_phytype = WMPHY_M88; + break; + case MII_MODEL_xxMARVELL_I82563: + new_phytype = WMPHY_GG82563; + break; + default: + break; + } + break; + case MII_OUI_INTEL: + switch (phy_model) { + case MII_MODEL_INTEL_I82577: + new_phytype = WMPHY_82577; + break; + case MII_MODEL_INTEL_I82579: + new_phytype = WMPHY_82579; + break; + case MII_MODEL_INTEL_I217: + new_phytype = WMPHY_I217; + break; + case MII_MODEL_INTEL_I82580: + case MII_MODEL_INTEL_I350: + new_phytype = WMPHY_82580; + break; + default: + break; + } + break; + case MII_OUI_yyINTEL: + switch (phy_model) { + case MII_MODEL_yyINTEL_I82562G: + case MII_MODEL_yyINTEL_I82562EM: + case MII_MODEL_yyINTEL_I82562ET: + new_phytype = WMPHY_IFE; + break; + case MII_MODEL_yyINTEL_IGP01E1000: + new_phytype = WMPHY_IGP; + break; + case MII_MODEL_yyINTEL_I82566: + new_phytype = WMPHY_IGP_3; + break; + default: + break; + } + break; + default: + break; + } + if (new_phytype == WMPHY_UNKNOWN) + aprint_verbose_dev(dev, "%s: unknown PHY model\n", + __func__); + + if ((sc->sc_phytype != WMPHY_UNKNOWN) + && (sc->sc_phytype != new_phytype )) { + aprint_error_dev(dev, "Previously assumed PHY type(%u)" + "was incorrect. PHY type from PHY ID = %u\n", + sc->sc_phytype, new_phytype); + } + } + + /* Next, use sc->sc_flags and sc->sc_type to set read/write funcs. */ + if (((sc->sc_flags & WM_F_SGMII) != 0) && !wm_sgmii_uses_mdio(sc)) { + /* SGMII */ + new_readreg = wm_sgmii_readreg; + new_writereg = wm_sgmii_writereg; + } else if ((sc->sc_type == WM_T_82574) || (sc->sc_type == WM_T_82583)){ + /* BM2 (phyaddr == 1) */ + if ((sc->sc_phytype != WMPHY_UNKNOWN) + && (new_phytype != WMPHY_BM) + && (new_phytype != WMPHY_UNKNOWN)) + doubt_phytype = new_phytype; + new_phytype = WMPHY_BM; + new_readreg = wm_gmii_bm_readreg; + new_writereg = wm_gmii_bm_writereg; + } else if (sc->sc_type >= WM_T_PCH) { + /* All PCH* use _hv_ */ + new_readreg = wm_gmii_hv_readreg; + new_writereg = wm_gmii_hv_writereg; + } else if (sc->sc_type >= WM_T_ICH8) { + /* non-82567 ICH8, 9 and 10 */ + new_readreg = wm_gmii_i82544_readreg; + new_writereg = wm_gmii_i82544_writereg; + } else if (sc->sc_type >= WM_T_80003) { + /* 80003 */ + if ((sc->sc_phytype != WMPHY_UNKNOWN) + && (new_phytype != WMPHY_GG82563) + && (new_phytype != WMPHY_UNKNOWN)) + doubt_phytype = new_phytype; + new_phytype = WMPHY_GG82563; + new_readreg = wm_gmii_i80003_readreg; + new_writereg = wm_gmii_i80003_writereg; + } else if (sc->sc_type >= WM_T_I210) { + /* I210 and I211 */ + if ((sc->sc_phytype != WMPHY_UNKNOWN) + && (new_phytype != WMPHY_I210) + && (new_phytype != WMPHY_UNKNOWN)) + doubt_phytype = new_phytype; + new_phytype = WMPHY_I210; + new_readreg = wm_gmii_gs40g_readreg; + new_writereg = wm_gmii_gs40g_writereg; + } else if (sc->sc_type >= WM_T_82580) { + /* 82580, I350 and I354 */ + new_readreg = wm_gmii_82580_readreg; + new_writereg = wm_gmii_82580_writereg; + } else if (sc->sc_type >= WM_T_82544) { + /* 82544, 0, [56], [17], 8257[1234] and 82583 */ + new_readreg = wm_gmii_i82544_readreg; + new_writereg = wm_gmii_i82544_writereg; + } else { + new_readreg = wm_gmii_i82543_readreg; + new_writereg = wm_gmii_i82543_writereg; + } + + if (new_phytype == WMPHY_BM) { + /* All BM use _bm_ */ + new_readreg = wm_gmii_bm_readreg; + new_writereg = wm_gmii_bm_writereg; + } + if ((sc->sc_type >= WM_T_PCH) && (sc->sc_type <= WM_T_PCH_SPT)) { + /* All PCH* use _hv_ */ + new_readreg = wm_gmii_hv_readreg; + new_writereg = wm_gmii_hv_writereg; + } + + /* Diag output */ + if (doubt_phytype != WMPHY_UNKNOWN) + aprint_error_dev(dev, "Assumed new PHY type was " + "incorrect. old = %u, new = %u\n", sc->sc_phytype, + new_phytype); + else if ((sc->sc_phytype != WMPHY_UNKNOWN) + && (sc->sc_phytype != new_phytype )) + aprint_error_dev(dev, "Previously assumed PHY type(%u)" + "was incorrect. New PHY type = %u\n", + sc->sc_phytype, new_phytype); + + if ((mii->mii_readreg != NULL) && (new_phytype == WMPHY_UNKNOWN)) + aprint_error_dev(dev, "PHY type is still unknown.\n"); + + if ((mii->mii_readreg != NULL) && (mii->mii_readreg != new_readreg)) + aprint_error_dev(dev, "Previously assumed PHY read/write " + "function was incorrect.\n"); + + /* Update now */ + sc->sc_phytype = new_phytype; + mii->mii_readreg = new_readreg; + mii->mii_writereg = new_writereg; +} + +/* * wm_get_phy_id_82575: * * Return PHY ID. Return -1 if it failed. @@ -6844,6 +7104,7 @@ wm_get_phy_id_82575(struct wm_softc *sc) static void wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid) { + device_t dev = sc->sc_dev; struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct mii_data *mii = &sc->sc_mii; uint32_t reg; @@ -6881,93 +7142,11 @@ wm_gmii_mediainit(struct wm_softc *sc, p mii->mii_ifp = ifp; /* - * Determine the PHY access method. - * - * For SGMII, use SGMII specific method. - * - * For some devices, we can determine the PHY access method - * from sc_type. - * - * For ICH and PCH variants, it's difficult to determine the PHY - * access method by sc_type, so use the PCI product ID for some - * devices. - * For other ICH8 variants, try to use igp's method. If the PHY - * can't detect, then use bm's method. - */ - switch (prodid) { - case PCI_PRODUCT_INTEL_PCH_M_LM: - case PCI_PRODUCT_INTEL_PCH_M_LC: - /* 82577 */ - sc->sc_phytype = WMPHY_82577; - break; - case PCI_PRODUCT_INTEL_PCH_D_DM: - case PCI_PRODUCT_INTEL_PCH_D_DC: - /* 82578 */ - sc->sc_phytype = WMPHY_82578; - break; - case PCI_PRODUCT_INTEL_PCH2_LV_LM: - case PCI_PRODUCT_INTEL_PCH2_LV_V: - /* 82579 */ - sc->sc_phytype = WMPHY_82579; - break; - case PCI_PRODUCT_INTEL_82801H_82567V_3: - case PCI_PRODUCT_INTEL_82801I_BM: - case PCI_PRODUCT_INTEL_82801J_R_BM_LM: - case PCI_PRODUCT_INTEL_82801J_R_BM_LF: - case PCI_PRODUCT_INTEL_82801J_D_BM_LM: - case PCI_PRODUCT_INTEL_82801J_D_BM_LF: - case PCI_PRODUCT_INTEL_82801J_R_BM_V: - /* ICH8, 9, 10 with 82567 */ - sc->sc_phytype = WMPHY_BM; - mii->mii_readreg = wm_gmii_bm_readreg; - mii->mii_writereg = wm_gmii_bm_writereg; - break; - default: - if (((sc->sc_flags & WM_F_SGMII) != 0) - && !wm_sgmii_uses_mdio(sc)){ - /* SGMII */ - mii->mii_readreg = wm_sgmii_readreg; - mii->mii_writereg = wm_sgmii_writereg; - } else if ((sc->sc_type == WM_T_82574) - || (sc->sc_type == WM_T_82583)) { - /* BM2 (phyaddr == 1) */ - sc->sc_phytype = WMPHY_BM; - mii->mii_readreg = wm_gmii_bm_readreg; - mii->mii_writereg = wm_gmii_bm_writereg; - } else if (sc->sc_type >= WM_T_ICH8) { - /* non-82567 ICH8, 9 and 10 */ - mii->mii_readreg = wm_gmii_i82544_readreg; - mii->mii_writereg = wm_gmii_i82544_writereg; - } else if (sc->sc_type >= WM_T_80003) { - /* 80003 */ - sc->sc_phytype = WMPHY_GG82563; - mii->mii_readreg = wm_gmii_i80003_readreg; - mii->mii_writereg = wm_gmii_i80003_writereg; - } else if (sc->sc_type >= WM_T_I210) { - /* I210 and I211 */ - sc->sc_phytype = WMPHY_210; - mii->mii_readreg = wm_gmii_gs40g_readreg; - mii->mii_writereg = wm_gmii_gs40g_writereg; - } else if (sc->sc_type >= WM_T_82580) { - /* 82580, I350 and I354 */ - sc->sc_phytype = WMPHY_82580; - mii->mii_readreg = wm_gmii_82580_readreg; - mii->mii_writereg = wm_gmii_82580_writereg; - } else if (sc->sc_type >= WM_T_82544) { - /* 82544, 0, [56], [17], 8257[1234] and 82583 */ - mii->mii_readreg = wm_gmii_i82544_readreg; - mii->mii_writereg = wm_gmii_i82544_writereg; - } else { - mii->mii_readreg = wm_gmii_i82543_readreg; - mii->mii_writereg = wm_gmii_i82543_writereg; - } - break; - } - if ((sc->sc_type >= WM_T_PCH) && (sc->sc_type <= WM_T_PCH_SPT)) { - /* All PCH* use _hv_ */ - mii->mii_readreg = wm_gmii_hv_readreg; - mii->mii_writereg = wm_gmii_hv_writereg; - } + * The first call of wm_mii_setup_phytype. The result might be + * incorrect. + */ + wm_gmii_setup_phytype(sc, 0, 0); + mii->mii_statchg = wm_gmii_statchg; /* get PHY control from SMBus to PCIe */ @@ -7039,6 +7218,10 @@ wm_gmii_mediainit(struct wm_softc *sc, p */ if (LIST_FIRST(&mii->mii_phys) == NULL) { /* if failed, retry with *_bm_* */ + aprint_verbose_dev(dev, "Assumed PHY access function " + "(type = %d) might be incorrect. Use BM and retry.\n", + sc->sc_phytype); + sc->sc_phytype = WMPHY_BM; mii->mii_readreg = wm_gmii_bm_readreg; mii->mii_writereg = wm_gmii_bm_writereg; @@ -7052,17 +7235,14 @@ wm_gmii_mediainit(struct wm_softc *sc, p ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); sc->sc_phytype = WMPHY_NONE; } else { + struct mii_softc *child = LIST_FIRST(&mii->mii_phys); + /* - * PHY Found! - * Check PHY type. + * PHY Found! Check PHY type again by the second call of + * wm_mii_setup_phytype. */ - uint32_t model; - struct mii_softc *child; - - child = LIST_FIRST(&mii->mii_phys); - model = child->mii_mpd_model; - if (model == MII_MODEL_yyINTEL_I82566) - sc->sc_phytype = WMPHY_IGP_3; + wm_gmii_setup_phytype(sc, child->mii_mpd_oui, + child->mii_mpd_model); ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); } Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.60.2.7 src/sys/dev/pci/if_wmreg.h:1.60.2.8 --- src/sys/dev/pci/if_wmreg.h:1.60.2.7 Sun Dec 18 07:53:09 2016 +++ src/sys/dev/pci/if_wmreg.h Thu Mar 9 06:28:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.60.2.7 2016/12/18 07:53:09 snj Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.60.2.8 2017/03/09 06:28:36 snj Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -897,7 +897,7 @@ struct livengood_tcpip_ctxdesc { #define WUC_APME 0x00000001 /* APM Enable */ #define WUC_PME_EN 0x00000002 /* PME Enable */ -#define WMREG_WUFC 0x5808 /* Wakeup Filter COntrol */ +#define WMREG_WUFC 0x5808 /* Wakeup Filter Control */ #define WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ #define WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define WUFC_MC 0x00000008 /* Directed Multicast Wakeup En */ Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.19.2.5 src/sys/dev/pci/if_wmvar.h:1.19.2.6 --- src/sys/dev/pci/if_wmvar.h:1.19.2.5 Mon Dec 12 07:18:29 2016 +++ src/sys/dev/pci/if_wmvar.h Thu Mar 9 06:28:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.19.2.5 2016/12/12 07:18:29 snj Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.19.2.6 2017/03/09 06:28:36 snj Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -168,7 +168,7 @@ typedef enum { WMPHY_I217, WMPHY_82580, WMPHY_VF, - WMPHY_210 + WMPHY_I210 } wm_phy_type;