Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Fixes the rx stall problem on 82578 by MANY workarou...



details:   https://anonhg.NetBSD.org/src/rev/c0c1915d45ed
branches:  trunk
changeset: 750795:c0c1915d45ed
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Jan 14 18:56:01 2010 +0000

description:
Fixes the rx stall problem on 82578 by MANY workaround code.
We need more work for 82577.

diffstat:

 sys/dev/mii/inbmphyreg.h |  110 ++++++++++
 sys/dev/pci/if_wm.c      |  489 +++++++++++++++++++++++++++++++++++-----------
 sys/dev/pci/if_wmreg.h   |   10 +-
 sys/dev/pci/if_wmvar.h   |   17 +-
 4 files changed, 504 insertions(+), 122 deletions(-)

diffs (truncated from 919 to 300 lines):

diff -r 118fd9f5f35b -r c0c1915d45ed sys/dev/mii/inbmphyreg.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/mii/inbmphyreg.h  Thu Jan 14 18:56:01 2010 +0000
@@ -0,0 +1,110 @@
+/*     $NetBSD: inbmphyreg.h,v 1.1 2010/01/14 18:56:01 msaitoh Exp $   */
+/*******************************************************************************
+Copyright (c) 2001-2005, Intel Corporation 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, 
+    this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright 
+    notice, this list of conditions and the following disclaimer in the 
+    documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its 
+    contributors may be used to endorse or promote products derived from 
+    this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/*
+ * Copied from the Intel code, and then modified to match NetBSD
+ * style for MII registers more.
+ */
+
+#ifndef _DEV_MII_INBMPHYREG_H_
+#define        _DEV_MII_INBMPHYREG_H_
+
+/* Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define BME1000_PAGE_SHIFT        5
+#define BME1000_REG(page, reg)    \
+        (((page) << BME1000_PAGE_SHIFT) | ((reg) & BME1000_MAX_REG_ADDRESS))
+
+#define BME1000_MAX_REG_ADDRESS        0x1f  /* 5 bit address bus (0-0x1f) */
+#define BME1000_MAX_MULTI_PAGE_REG     0xf   /* Registers equal on all pages */
+
+#define        BM_PHY_REG_PAGE(offset)                 \
+       ((uint16_t)(((offset) >> BME1000_PAGE_SHIFT) & 0xffff))
+#define        BM_PHY_REG_NUM(offset)                  \
+       ((uint16_t)((offset) & BME1000_MAX_REG_ADDRESS)         \
+       | (((offset) >> (21 - BME1000_PAGE_SHIFT)) & ~BME1000_MAX_REG_ADDRESS))
+
+/* BME1000 Specific Registers */
+#define BME1000_PHY_SPEC_CTRL  BME1000_REG(0, 16) /* PHY Specific Control */
+#define BME1000_PSCR_DISABLE_JABBER             0x0001 /* 1=Disable Jabber */
+#define BME1000_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Polarity Reversal Disabled */
+#define BME1000_PSCR_POWER_DOWN                 0x0004 /* 1=Power Down */
+#define BME1000_PSCR_COPPER_TRANSMITER_DISABLE  0x0008 /* 1=Transmitter Disabled */
+#define BME1000_PSCR_CROSSOVER_MODE_MASK        0x0060
+#define BME1000_PSCR_CROSSOVER_MODE_MDI         0x0000 /* 00=Manual MDI configuration */
+#define BME1000_PSCR_CROSSOVER_MODE_MDIX        0x0020 /* 01=Manual MDIX configuration */
+#define BME1000_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Automatic crossover */
+#define BME1000_PSCR_ENALBE_EXTENDED_DISTANCE   0x0080 /* 1=Enable Extended Distance */
+#define BME1000_PSCR_ENERGY_DETECT_MASK         0x0300
+#define BME1000_PSCR_ENERGY_DETECT_OFF          0x0000 /* 00,01=Off */
+#define BME1000_PSCR_ENERGY_DETECT_RX           0x0200 /* 10=Sense on Rx only (Energy Detect) */
+#define BME1000_PSCR_ENERGY_DETECT_RX_TM        0x0300 /* 11=Sense and Tx NLP */
+#define BME1000_PSCR_FORCE_LINK_GOOD            0x0400 /* 1=Force Link Good */
+#define BME1000_PSCR_DOWNSHIFT_ENABLE           0x0800 /* 1=Enable Downshift */
+#define BME1000_PSCR_DOWNSHIFT_COUNTER_MASK     0x7000
+#define BME1000_PSCR_DOWNSHIFT_COUNTER_SHIFT    12
+
+#define BME1000_PHY_PAGE_SELECT        BME1000_REG(0, 22) /* Page Select */
+
+#define BME1000_BIAS_SETTING   29
+#define BME1000_BIAS_SETTING2  30
+
+#define        I82578_ADDR_REG         29
+#define        I82577_ADDR_REG         16
+#define        I82577_CFG_REG          22
+
+#define HV_OEM_BITS            BME1000_REG(0, 25)
+#define HV_OEM_BITS_LPLU       (1 << 2)
+#define HV_OEM_BITS_A1KDIS     (1 << 6)
+#define HV_OEM_BITS_ANEGNOW    (1 << 10)
+
+#define HV_INTC_FC_PAGE_START  768
+#define        BM_PORT_CTRL_PAGE       769
+
+#define        IGP3_KMRN_DIAG          BME1000_REG(770, 19)
+
+#define HV_MUX_DATA_CTRL       BME1000_REG(776, 16)
+#define HV_MUX_DATA_CTRL_FORCE_SPEED   (1 << 2)
+#define HV_MUX_DATA_CTRL_GEN_TO_MAC    (1 << 10)
+
+#define        BM_WUC_PAGE             800
+#define        BM_WUC                  BME1000_REG(BM_WUC_PAGE, 1)
+#define        BM_WUC_ADDRESS_OPCODE   0x11
+#define        BM_WUC_DATA_OPCODE      0x12
+#define        BM_WUC_ENABLE_PAGE      BM_PORT_CTRL_PAGE
+#define        BM_WUC_ENABLE_REG       17
+#define        BM_WUC_ENABLE_BIT       (1 << 2)
+#define        BM_WUC_HOST_WU_BIT      (1 << 4)
+
+#endif /* _DEV_MII_INBMPHYREG_H_ */
diff -r 118fd9f5f35b -r c0c1915d45ed sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Jan 14 17:49:31 2010 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Jan 14 18:56:01 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.191 2010/01/12 22:26:30 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.192 2010/01/14 18:56:02 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.191 2010/01/12 22:26:30 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.192 2010/01/14 18:56:02 msaitoh Exp $");
 
 #include "bpfilter.h"
 #include "rnd.h"
@@ -124,6 +124,7 @@
 #include <dev/mii/mii_bitbang.h>
 #include <dev/mii/ikphyreg.h>
 #include <dev/mii/igphyreg.h>
+#include <dev/mii/inbmphyreg.h>
 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
@@ -249,7 +250,9 @@
        pci_chipset_tag_t sc_pc;
        pcitag_t sc_pcitag;
 
-       wm_chip_type sc_type;           /* chip type */
+       wm_chip_type sc_type;           /* MAC type */
+       int sc_rev;                     /* MAC revision */
+       wm_phy_type sc_phytype;         /* PHY type */
        int sc_flags;                   /* flags; see below */
        int sc_if_flags;                /* last if_flags */
        int sc_bus_speed;               /* PCI/PCIX bus speed */
@@ -366,6 +369,7 @@
 #endif
        int sc_ich8_flash_base;
        int sc_ich8_flash_bank_size;
+       int sc_nvm_k1_enabled;
 };
 
 #define        WM_RXCHAIN_RESET(sc)                                            \
@@ -520,8 +524,8 @@
 static void    wm_gmii_i80003_writereg(device_t, int, int, int);
 static int     wm_gmii_bm_readreg(device_t, int, int);
 static void    wm_gmii_bm_writereg(device_t, int, int, int);
-static int     wm_gmii_kv_readreg(device_t, int, int);
-static void    wm_gmii_kv_writereg(device_t, int, int, int);
+static int     wm_gmii_hv_readreg(device_t, int, int);
+static void    wm_gmii_hv_writereg(device_t, int, int, int);
 
 static void    wm_gmii_statchg(device_t);
 
@@ -562,6 +566,9 @@
 static int     wm_check_reset_block(struct wm_softc *);
 static void    wm_get_hw_control(struct wm_softc *);
 static int     wm_check_for_link(struct wm_softc *);
+static void    wm_hv_phy_workaround_ich8lan(struct wm_softc *);
+static void    wm_k1_gig_workaround_hv(struct wm_softc *, int);
+static void    wm_configure_k1_ich8lan(struct wm_softc *, int);
 
 CFATTACH_DECL_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, NULL, NULL);
@@ -991,18 +998,18 @@
        else
                sc->sc_dmat = pa->pa_dmat;
 
-       preg = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
+       sc->sc_rev = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
        aprint_naive(": Ethernet controller\n");
-       aprint_normal(": %s, rev. %d\n", wmp->wmp_name, preg);
+       aprint_normal(": %s, rev. %d\n", wmp->wmp_name, sc->sc_rev);
 
        sc->sc_type = wmp->wmp_type;
        if (sc->sc_type < WM_T_82543) {
-               if (preg < 2) {
+               if (sc->sc_rev < 2) {
                        aprint_error_dev(sc->sc_dev,
                            "i82542 must be at least rev. 2\n");
                        return;
                }
-               if (preg < 3)
+               if (sc->sc_rev < 3)
                        sc->sc_type = WM_T_82542_2_0;
        }
 
@@ -1575,6 +1582,18 @@
                sc->sc_tdt_reg = WMREG_TDT;
        }
 
+       if (sc->sc_type == WM_T_PCH) {
+               uint16_t val;
+
+               /* Save the NVM K1 bit setting */
+               wm_read_eeprom(sc, EEPROM_OFF_K1_CONFIG, 1, &val);
+
+               if ((val & EEPROM_K1_CONFIG_ENABLE) != 0)
+                       sc->sc_nvm_k1_enabled = 1;
+               else
+                       sc->sc_nvm_k1_enabled = 0;
+       }
+
        /*
         * Determine if we're TBI or GMII mode, and initialize the
         * media structures accordingly.
@@ -2896,74 +2915,101 @@
 }
 
 /*
- * wm_linkintr:
+ * wm_linkintr_gmii:
  *
- *     Helper; handle link interrupts.
+ *     Helper; handle link interrupts for GMII.
  */
 static void
-wm_linkintr(struct wm_softc *sc, uint32_t icr)
+wm_linkintr_gmii(struct wm_softc *sc, uint32_t icr)
+{
+
+       DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
+               __func__));
+
+       if (icr & ICR_LSC) {
+               DPRINTF(WM_DEBUG_LINK,
+                   ("%s: LINK: LSC -> mii_tick\n",
+                       device_xname(sc->sc_dev)));
+               mii_tick(&sc->sc_mii);
+               if (sc->sc_type == WM_T_82543) {
+                       int miistatus, active;
+
+                       /*
+                        * With 82543, we need to force speed and
+                        * duplex on the MAC equal to what the PHY
+                        * speed and duplex configuration is.
+                        */
+                       miistatus = sc->sc_mii.mii_media_status;
+
+                       if (miistatus & IFM_ACTIVE) {
+                               active = sc->sc_mii.mii_media_active;
+                               sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
+                               switch (IFM_SUBTYPE(active)) {
+                               case IFM_10_T:
+                                       sc->sc_ctrl |= CTRL_SPEED_10;
+                                       break;
+                               case IFM_100_TX:
+                                       sc->sc_ctrl |= CTRL_SPEED_100;
+                                       break;
+                               case IFM_1000_T:
+                                       sc->sc_ctrl |= CTRL_SPEED_1000;
+                                       break;
+                               default:
+                                       /*
+                                        * fiber?
+                                        * Shoud not enter here.
+                                        */
+                                       printf("unknown media (%x)\n",
+                                           active);
+                                       break;
+                               }
+                               if (active & IFM_FDX)
+                                       sc->sc_ctrl |= CTRL_FD;
+                               CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+                       }
+               } else if (sc->sc_type == WM_T_PCH) {
+                       wm_k1_gig_workaround_hv(sc,
+                           ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0));
+               }
+
+               if ((sc->sc_phytype == WMPHY_82578)
+                   && (IFM_SUBTYPE(sc->sc_mii.mii_media_active)
+                       == IFM_1000_T)) {
+
+                       if ((sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0) {
+                               printf("XXX link sall wa\n");
+                               delay(200*1000); /* XXX too big */
+
+                               /* Link stall fix for link up */
+                               wm_gmii_hv_writereg(sc->sc_dev, 1,
+                                   HV_MUX_DATA_CTRL,
+                                   HV_MUX_DATA_CTRL_GEN_TO_MAC
+                                   | HV_MUX_DATA_CTRL_FORCE_SPEED);
+                               wm_gmii_hv_writereg(sc->sc_dev, 1,



Home | Main Index | Thread Index | Old Index