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/43633b8ea115
branches:  netbsd-7
changeset: 799096:43633b8ea115
user:      snj <snj%NetBSD.org@localhost>
date:      Wed Mar 18 04:39:15 2015 +0000

description:
Pull up following revision(s) (requested by msaitoh in ticket #614):
        sys/dev/pci/if_wm.c: revision 1.311-1.313
        sys/dev/pci/if_wmreg.h: revision 1.66
Fix a bug that sc_mediatype is evaluated incorrectly. The real problem
might be occured only on fiber and serdes cases.
#####
- Initialize some hardware bits for 8257[1234], 82583, 80003, ICH* and PCH*.
  Some of them are workaround code. From other *BSDs, Linux and documents.
- Add comment.
- Fix typo in comment.
#####
 Fix a bug that the first access to NVM is failed on 8254[17] which use
SPI EEPROM. Observed on Dell PowerEdge [12]850. Thanks Tom Ivar Helbekkmo
for debugging.

diffstat:

 sys/dev/pci/if_wm.c    |  277 +++++++++++++++++++++++++++++++++++++++++-------
 sys/dev/pci/if_wmreg.h |   22 +++-
 2 files changed, 255 insertions(+), 44 deletions(-)

diffs (truncated from 561 to 300 lines):

diff -r 22c396fe4a5f -r 43633b8ea115 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Mar 18 03:57:15 2015 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Mar 18 04:39:15 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.289.2.3 2015/02/04 06:48:13 snj Exp $      */
+/*     $NetBSD: if_wm.c,v 1.289.2.4 2015/03/18 04:39:15 snj Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -81,7 +81,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.289.2.3 2015/02/04 06:48:13 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.289.2.4 2015/03/18 04:39:15 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -277,6 +277,10 @@
        int sc_rev;                     /* MAC revision */
        wm_phy_type sc_phytype;         /* PHY type */
        uint32_t sc_mediatype;          /* Media type (Copper, Fiber, SERDES)*/
+#define        WM_MEDIATYPE_UNKNOWN            0x00
+#define        WM_MEDIATYPE_FIBER              0x01
+#define        WM_MEDIATYPE_COPPER             0x02
+#define        WM_MEDIATYPE_SERDES             0x03 /* Internal SERDES */
        int sc_funcid;                  /* unit number of the chip (0 to 3) */
        int sc_flags;                   /* flags; see below */
        int sc_if_flags;                /* last if_flags */
@@ -557,6 +561,7 @@
 static void    wm_get_auto_rd_done(struct wm_softc *);
 static void    wm_lan_init_done(struct wm_softc *);
 static void    wm_get_cfg_done(struct wm_softc *);
+static void    wm_initialize_hardware_bits(struct wm_softc *);
 static void    wm_reset(struct wm_softc *);
 static int     wm_add_rxbuf(struct wm_softc *, int);
 static void    wm_rxdrain(struct wm_softc *);
@@ -723,10 +728,10 @@
        const char              *wmp_name;
        wm_chip_type            wmp_type;
        uint32_t                wmp_flags;
-#define        WMP_F_UNKNOWN           0x00
-#define        WMP_F_FIBER             0x01
-#define        WMP_F_COPPER            0x02
-#define        WMP_F_SERDES            0x03 /* Internal SERDES */
+#define        WMP_F_UNKNOWN           WM_MEDIATYPE_UNKNOWN
+#define        WMP_F_FIBER             WM_MEDIATYPE_FIBER
+#define        WMP_F_COPPER            WM_MEDIATYPE_COPPER
+#define        WMP_F_SERDES            WM_MEDIATYPE_SERDES
 #define WMP_MEDIATYPE(x)       ((x) & 0x03)
 } wm_products[] = {
        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82542,
@@ -1739,6 +1744,7 @@
        case WM_T_82541_2:
        case WM_T_82547:
        case WM_T_82547_2:
+               sc->sc_flags |= WM_F_LOCK_EECD;
                reg = CSR_READ(sc, WMREG_EECD);
                if (reg & EECD_EE_TYPE) {
                        /* SPI */
@@ -1754,7 +1760,6 @@
                                sc->sc_nvm_addrbits = 6;
                        }
                }
-               sc->sc_flags |= WM_F_LOCK_EECD;
                break;
        case WM_T_82571:
        case WM_T_82572:
@@ -2106,10 +2111,10 @@
                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 & WMP_F_COPPER) {
+               if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) {
                        aprint_error_dev(sc->sc_dev,
                            "WARNING: TBIMODE set on 1000BASE-T product!\n");
-                       sc->sc_mediatype = WMP_F_FIBER;
+                       sc->sc_mediatype = WM_MEDIATYPE_FIBER;
                }
                wm_tbi_mediainit(sc);
        } else {
@@ -2126,45 +2131,45 @@
                        switch (link_mode) {
                        case CTRL_EXT_LINK_MODE_1000KX:
                                aprint_verbose_dev(sc->sc_dev, "1000KX\n");
-                               sc->sc_mediatype = WMP_F_SERDES;
+                               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 = WMP_F_COPPER;
+                                       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 == WMP_F_UNKNOWN) {
+                               if (sc->sc_mediatype == WM_MEDIATYPE_UNKNOWN) {
                                        if (link_mode
                                            == CTRL_EXT_LINK_MODE_SGMII) {
                                                sc->sc_mediatype
-                                                   = WMP_F_COPPER;
+                                                   = WM_MEDIATYPE_COPPER;
                                                sc->sc_flags |= WM_F_SGMII;
                                        } else {
                                                sc->sc_mediatype
-                                                   = WMP_F_SERDES;
+                                                   = WM_MEDIATYPE_SERDES;
                                                aprint_verbose_dev(sc->sc_dev,
                                                    "SERDES\n");
                                        }
                                        break;
                                }
-                               if (sc->sc_mediatype == WMP_F_SERDES)
+                               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 WMP_F_COPPER:
+                               case WM_MEDIATYPE_COPPER:
                                        reg |= CTRL_EXT_LINK_MODE_SGMII;
                                        break;
-                               case WMP_F_SERDES:
+                               case WM_MEDIATYPE_SERDES:
                                        reg |= CTRL_EXT_LINK_MODE_PCIE_SERDES;
                                        break;
                                default:
@@ -2175,7 +2180,7 @@
                        case CTRL_EXT_LINK_MODE_GMII:
                        default:
                                aprint_verbose_dev(sc->sc_dev, "Copper\n");
-                               sc->sc_mediatype = WMP_F_COPPER;
+                               sc->sc_mediatype = WM_MEDIATYPE_COPPER;
                                break;
                        }
 
@@ -2186,16 +2191,16 @@
                                reg &= ~CTRL_EXT_I2C_ENA;
                        CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
 
-                       if (sc->sc_mediatype == WMP_F_COPPER)
+                       if (sc->sc_mediatype == WM_MEDIATYPE_COPPER)
                                wm_gmii_mediainit(sc, wmp->wmp_product);
                        else
                                wm_tbi_mediainit(sc);
                        break;
                default:
-                       if (sc->sc_mediatype & WMP_F_FIBER)
+                       if (sc->sc_mediatype == WM_MEDIATYPE_FIBER)
                                aprint_error_dev(sc->sc_dev,
                                    "WARNING: TBIMODE clear on 1000BASE-X product!\n");
-                       sc->sc_mediatype = WMP_F_COPPER;
+                       sc->sc_mediatype = WM_MEDIATYPE_COPPER;
                        wm_gmii_mediainit(sc, wmp->wmp_product);
                }
        }
@@ -3209,6 +3214,200 @@
        }
 }
 
+/* Init hardware bits */
+void
+wm_initialize_hardware_bits(struct wm_softc *sc)
+{
+       uint32_t tarc0, tarc1, reg;
+       
+       /* For 82571 variant, 80003 and ICHs */
+       if (((sc->sc_type >= WM_T_82571) && (sc->sc_type <= WM_T_82583))
+           || (sc->sc_type >= WM_T_80003)) {
+
+               /* Transmit Descriptor Control 0 */
+               reg = CSR_READ(sc, WMREG_TXDCTL(0));
+               reg |= TXDCTL_COUNT_DESC;
+               CSR_WRITE(sc, WMREG_TXDCTL(0), reg);
+
+               /* Transmit Descriptor Control 1 */
+               reg = CSR_READ(sc, WMREG_TXDCTL(1));
+               reg |= TXDCTL_COUNT_DESC;
+               CSR_WRITE(sc, WMREG_TXDCTL(1), reg);
+
+               /* TARC0 */
+               tarc0 = CSR_READ(sc, WMREG_TARC0);
+               switch (sc->sc_type) {
+               case WM_T_82571:
+               case WM_T_82572:
+               case WM_T_82573:
+               case WM_T_82574:
+               case WM_T_82583:
+               case WM_T_80003:
+                       /* Clear bits 30..27 */
+                       tarc0 &= ~__BITS(30, 27);
+                       break;
+               default:
+                       break;
+               }
+
+               switch (sc->sc_type) {
+               case WM_T_82571:
+               case WM_T_82572:
+                       tarc0 |= __BITS(26, 23); /* TARC0 bits 23-26 */
+
+                       tarc1 = CSR_READ(sc, WMREG_TARC1);
+                       tarc1 &= ~__BITS(30, 29); /* Clear bits 30 and 29 */
+                       tarc1 |= __BITS(26, 24); /* TARC1 bits 26-24 */
+                       /* 8257[12] Errata No.7 */
+                       tarc1 |= __BIT(22); /* TARC1 bits 22 */
+
+                       /* TARC1 bit 28 */
+                       if ((CSR_READ(sc, WMREG_TCTL) & TCTL_MULR) != 0)
+                               tarc1 &= ~__BIT(28);
+                       else
+                               tarc1 |= __BIT(28);
+                       CSR_WRITE(sc, WMREG_TARC1, tarc1);
+
+                       /*
+                        * 8257[12] Errata No.13
+                        * Disable Dyamic Clock Gating.
+                        */
+                       reg = CSR_READ(sc, WMREG_CTRL_EXT);
+                       reg &= ~CTRL_EXT_DMA_DYN_CLK;
+                       CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+                       break;
+               case WM_T_82573:
+               case WM_T_82574:
+               case WM_T_82583:
+                       if ((sc->sc_type == WM_T_82574)
+                           || (sc->sc_type == WM_T_82583))
+                               tarc0 |= __BIT(26); /* TARC0 bit 26 */
+
+                       /* Extended Device Control */
+                       reg = CSR_READ(sc, WMREG_CTRL_EXT);
+                       reg &= ~__BIT(23);      /* Clear bit 23 */
+                       reg |= __BIT(22);       /* Set bit 22 */
+                       CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+
+                       /* Device Control */
+                       sc->sc_ctrl &= ~__BIT(29);      /* Clear bit 29 */
+                       CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+
+                       /* PCIe Control Register */
+                       if ((sc->sc_type == WM_T_82574)
+                           || (sc->sc_type == WM_T_82583)) {
+                               /*
+                                * Document says this bit must be set for
+                                * proper operation.
+                                */
+                               reg = CSR_READ(sc, WMREG_GCR);
+                               reg |= __BIT(22);
+                               CSR_WRITE(sc, WMREG_GCR, reg);
+
+                               /*
+                                * Apply workaround for hardware errata
+                                * documented in errata docs Fixes issue where
+                                * some error prone or unreliable PCIe
+                                * completions are occurring, particularly
+                                * with ASPM enabled. Without fix, issue can
+                                * cause Tx timeouts.
+                                */
+                               reg = CSR_READ(sc, WMREG_GCR2);
+                               reg |= __BIT(0);
+                               CSR_WRITE(sc, WMREG_GCR2, reg);
+                       }
+                       break;
+               case WM_T_80003:
+                       /* TARC0 */
+                       if ((sc->sc_mediatype == WM_MEDIATYPE_FIBER)
+                           || (sc->sc_mediatype == WM_MEDIATYPE_SERDES))
+                               tarc0 &= ~__BIT(20); /* Clear bits 20 */
+
+                       /* TARC1 bit 28 */
+                       tarc1 = CSR_READ(sc, WMREG_TARC1);
+                       if ((CSR_READ(sc, WMREG_TCTL) & TCTL_MULR) != 0)
+                               tarc1 &= ~__BIT(28);
+                       else
+                               tarc1 |= __BIT(28);
+                       CSR_WRITE(sc, WMREG_TARC1, tarc1);
+                       break;
+               case WM_T_ICH8:
+               case WM_T_ICH9:
+               case WM_T_ICH10:
+               case WM_T_PCH:
+               case WM_T_PCH2:
+               case WM_T_PCH_LPT:
+                       /* TARC 0 */
+                       if (sc->sc_type == WM_T_ICH8) {
+                               /* Set TARC0 bits 29 and 28 */
+                               tarc0 |= __BITS(29, 28);
+                       }
+                       /* Set TARC0 bits 23,24,26,27 */
+                       tarc0 |= __BITS(27, 26) | __BITS(24, 23);
+
+                       /* CTRL_EXT */



Home | Main Index | Thread Index | Old Index