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;