Source-Changes-HG archive

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

[src/netbsd-7]: src/sys/dev/pci Pull up following revision(s) (requested by m...



details:   https://anonhg.NetBSD.org/src/rev/4a9c81ac480c
branches:  netbsd-7
changeset: 800151:4a9c81ac480c
user:      snj <snj%NetBSD.org@localhost>
date:      Thu Mar 09 06:28:36 2017 +0000

description:
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.

diffstat:

 sys/dev/pci/if_wm.c    |  378 ++++++++++++++++++++++++++++++++++++------------
 sys/dev/pci/if_wmreg.h |    4 +-
 sys/dev/pci/if_wmvar.h |    4 +-
 3 files changed, 283 insertions(+), 103 deletions(-)

diffs (truncated from 490 to 300 lines):

diff -r 2131b91d9570 -r 4a9c81ac480c sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Mar 09 06:26:04 2017 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Mar 09 06:28:36 2017 +0000
@@ -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 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 @@
                }
                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 @@
                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 @@
 }
 
 /*
+ * 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))



Home | Main Index | Thread Index | Old Index