Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Fix a lot of bugs to make 82575 and newer's SERD...
details: https://anonhg.NetBSD.org/src/rev/13833f27e7be
branches: trunk
changeset: 338643:13833f27e7be
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Tue Jun 02 14:19:26 2015 +0000
description:
Fix a lot of bugs to make 82575 and newer's SERDES based systems work.
- Add SERDES specific functions.
- Fix IO pin configuration.
- Reset autonego timer when link becomes up.
TODO:
- Fix a bug that SFP ROM can't read.
- Perhaps some work is required for 8257[12] serdes systems.
- Remove duplicated code in TBI's link related functions.
diffstat:
sys/dev/pci/if_wm.c | 540 +++++++++++++++++++++++++++++++++++++++---------
sys/dev/pci/if_wmreg.h | 28 ++-
sys/dev/pci/if_wmvar.h | 3 +-
3 files changed, 466 insertions(+), 105 deletions(-)
diffs (truncated from 828 to 300 lines):
diff -r 4a486920a1ca -r 13833f27e7be sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Tue Jun 02 14:07:48 2015 +0000
+++ b/sys/dev/pci/if_wm.c Tue Jun 02 14:19:26 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.324 2015/06/02 13:26:36 msaitoh Exp $ */
+/* $NetBSD: if_wm.c,v 1.325 2015/06/02 14:19:26 msaitoh 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.324 2015/06/02 13:26:36 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.325 2015/06/02 14:19:26 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -392,8 +392,8 @@
uint32_t sc_pba; /* prototype PBA register */
int sc_tbi_linkup; /* TBI link status */
- int sc_tbi_anegticks; /* autonegotiation ticks */
- int sc_tbi_ticks; /* tbi ticks */
+ int sc_tbi_serdes_anegticks; /* autonegotiation ticks */
+ int sc_tbi_serdes_ticks; /* tbi ticks */
int sc_mchash_type; /* multicast filter offset */
@@ -595,6 +595,7 @@
static void wm_rxintr(struct wm_softc *);
static void wm_linkintr_gmii(struct wm_softc *, uint32_t);
static void wm_linkintr_tbi(struct wm_softc *, uint32_t);
+static void wm_linkintr_serdes(struct wm_softc *, uint32_t);
static void wm_linkintr(struct wm_softc *, uint32_t);
static int wm_intr(void *);
@@ -602,6 +603,8 @@
* Media related.
* GMII, SGMII, TBI, SERDES and SFP.
*/
+/* Common */
+static void wm_tbi_serdes_set_linkled(struct wm_softc *);
/* GMII related */
static void wm_gmii_reset(struct wm_softc *);
static int wm_get_phy_id_82575(struct wm_softc *);
@@ -631,12 +634,16 @@
static int wm_sgmii_readreg(device_t, int, int);
static void wm_sgmii_writereg(device_t, int, int, int);
/* TBI related */
-static int wm_check_for_link(struct wm_softc *);
static void wm_tbi_mediainit(struct wm_softc *);
static int wm_tbi_mediachange(struct ifnet *);
static void wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *);
-static void wm_tbi_set_linkled(struct wm_softc *);
-static void wm_tbi_check_link(struct wm_softc *);
+static int wm_check_for_link(struct wm_softc *);
+static void wm_tbi_tick(struct wm_softc *);
+/* SERDES related */
+static void wm_serdes_power_up_link_82575(struct wm_softc *);
+static int wm_serdes_mediachange(struct ifnet *);
+static void wm_serdes_mediastatus(struct ifnet *, struct ifmediareq *);
+static void wm_serdes_tick(struct wm_softc *);
/* SFP related */
static int wm_sfp_read_data_byte(struct wm_softc *, uint16_t, uint8_t *);
static uint32_t wm_sfp_get_media_type(struct wm_softc *);
@@ -728,6 +735,7 @@
static void wm_set_mdio_slow_mode_hv(struct wm_softc *);
static void wm_configure_k1_ich8lan(struct wm_softc *, int);
static void wm_reset_init_script_82575(struct wm_softc *);
+static void wm_reset_mdicnfg_82580(struct wm_softc *);
CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -1366,7 +1374,7 @@
prop_data_t ea;
prop_number_t pn;
uint8_t enaddr[ETHER_ADDR_LEN];
- uint16_t cfg1, cfg2, swdpin, io3;
+ uint16_t cfg1, cfg2, swdpin, nvmword;
pcireg_t preg, memtype;
uint16_t eeprom_data, apme_mask;
bool force_clear_smbi;
@@ -2046,6 +2054,14 @@
printf("WOL\n");
#endif
+ if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
+ /* Check NVM for autonegotiation */
+ if (wm_nvm_read(sc, NVM_OFF_COMPAT, 1, &nvmword) == 0) {
+ if ((nvmword & NVM_COMPAT_SERDES_FORCE_MODE) != 0)
+ sc->sc_flags |= WM_F_PCS_DIS_AUTONEGO;
+ }
+ }
+
/*
* XXX need special handling for some multiple port cards
* to disable a paticular port.
@@ -2067,17 +2083,37 @@
if (cfg1 & NVM_CFG1_ILOS)
sc->sc_ctrl |= CTRL_ILOS;
- if (sc->sc_type >= WM_T_82544) {
- sc->sc_ctrl |=
- ((swdpin >> NVM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
- CTRL_SWDPIO_SHIFT;
- sc->sc_ctrl |=
- ((swdpin >> NVM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
- CTRL_SWDPINS_SHIFT;
- } else {
- sc->sc_ctrl |=
- ((cfg1 >> NVM_CFG1_SWDPIO_SHIFT) & 0xf) <<
- CTRL_SWDPIO_SHIFT;
+
+ /*
+ * XXX
+ * This code isn't correct because pin 2 and 3 are located
+ * in different position on newer chips. Check all datasheet.
+ *
+ * Until resolve this problem, check if a chip < 82580
+ */
+ if (sc->sc_type <= WM_T_82580) {
+ if (sc->sc_type >= WM_T_82544) {
+ sc->sc_ctrl |=
+ ((swdpin >> NVM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
+ CTRL_SWDPIO_SHIFT;
+ sc->sc_ctrl |=
+ ((swdpin >> NVM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
+ CTRL_SWDPINS_SHIFT;
+ } else {
+ sc->sc_ctrl |=
+ ((cfg1 >> NVM_CFG1_SWDPIO_SHIFT) & 0xf) <<
+ CTRL_SWDPIO_SHIFT;
+ }
+ }
+
+ /* XXX For other than 82580? */
+ if (sc->sc_type == WM_T_82580) {
+ wm_nvm_read(sc, NVM_OFF_CFG3_PORTA, 1, &nvmword);
+ printf("CFG3 = %08x\n", (uint32_t)nvmword);
+ if (nvmword & __BIT(13)) {
+ printf("SET ILOS\n");
+ sc->sc_ctrl |= CTRL_ILOS;
+ }
}
#if 0
@@ -2255,8 +2291,8 @@
switch (sc->sc_type) {
case WM_T_82573:
/* XXX limited to 9234 if ASPM is disabled */
- wm_nvm_read(sc, NVM_OFF_INIT_3GIO_3, 1, &io3);
- if ((io3 & NVM_3GIO_3_ASPM_MASK) != 0)
+ wm_nvm_read(sc, NVM_OFF_INIT_3GIO_3, 1, &nvmword);
+ if ((nvmword & NVM_3GIO_3_ASPM_MASK) != 0)
sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
break;
case WM_T_82571:
@@ -2655,8 +2691,11 @@
if (sc->sc_flags & WM_F_HAS_MII)
mii_tick(&sc->sc_mii);
+ else if ((sc->sc_type >= WM_T_82575)
+ && (sc->sc_mediatype == WM_MEDIATYPE_SERDES))
+ wm_serdes_tick(sc);
else
- wm_tbi_check_link(sc);
+ wm_tbi_tick(sc);
out:
WM_TX_UNLOCK(sc);
@@ -3772,9 +3811,7 @@
switch (sc->sc_type) {
case WM_T_82575:
case WM_T_82576:
-#if 0 /* XXX */
case WM_T_82580:
-#endif
case WM_T_I350:
case WM_T_I354:
case WM_T_ICH8:
@@ -3782,11 +3819,7 @@
if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
/* Not found */
sc->sc_flags |= WM_F_EEPROM_INVALID;
- if ((sc->sc_type == WM_T_82575)
- || (sc->sc_type == WM_T_82576)
- || (sc->sc_type == WM_T_82580)
- || (sc->sc_type == WM_T_I350)
- || (sc->sc_type == WM_T_I354))
+ if (sc->sc_type == WM_T_82575)
wm_reset_init_script_82575(sc);
}
break;
@@ -3824,7 +3857,7 @@
if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
CSR_WRITE(sc, WMREG_WUC, 0);
- /* XXX need special handling for 82580 */
+ wm_reset_mdicnfg_82580(sc);
}
/*
@@ -6015,7 +6048,8 @@
device_xname(sc->sc_dev)));
sc->sc_tbi_linkup = 0;
}
- wm_tbi_set_linkled(sc);
+ /* Update LED */
+ wm_tbi_serdes_set_linkled(sc);
} else if (icr & ICR_RXSEQ) {
DPRINTF(WM_DEBUG_LINK,
("%s: LINK: Receive sequence error\n",
@@ -6024,6 +6058,76 @@
}
/*
+ * wm_linkintr_serdes:
+ *
+ * Helper; handle link interrupts for TBI mode.
+ */
+static void
+wm_linkintr_serdes(struct wm_softc *sc, uint32_t icr)
+{
+ struct mii_data *mii = &sc->sc_mii;
+ struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
+ uint32_t pcs_adv, pcs_lpab, reg;
+
+ DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev),
+ __func__));
+
+ if (icr & ICR_LSC) {
+ /* Check PCS */
+ reg = CSR_READ(sc, WMREG_PCS_LSTS);
+ if ((reg & PCS_LSTS_LINKOK) != 0) {
+ mii->mii_media_status |= IFM_ACTIVE;
+ sc->sc_tbi_linkup = 1;
+ } else {
+ mii->mii_media_status |= IFM_NONE;
+ sc->sc_tbi_linkup = 0;
+ wm_tbi_serdes_set_linkled(sc);
+ return;
+ }
+ mii->mii_media_active |= IFM_1000_SX;
+ if ((reg & PCS_LSTS_FDX) != 0)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+ /* Check flow */
+ reg = CSR_READ(sc, WMREG_PCS_LSTS);
+ if ((reg & PCS_LSTS_AN_COMP) == 0) {
+ DPRINTF(WM_DEBUG_LINK,
+ ("XXX LINKOK but not ACOMP\n"));
+ return;
+ }
+ pcs_adv = CSR_READ(sc, WMREG_PCS_ANADV);
+ pcs_lpab = CSR_READ(sc, WMREG_PCS_LPAB);
+ DPRINTF(WM_DEBUG_LINK,
+ ("XXX AN result %08x, %08x\n", pcs_adv, pcs_lpab));
+ if ((pcs_adv & TXCW_SYM_PAUSE)
+ && (pcs_lpab & TXCW_SYM_PAUSE)) {
+ mii->mii_media_active |= IFM_FLOW
+ | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
+ } else if (((pcs_adv & TXCW_SYM_PAUSE) == 0)
+ && (pcs_adv & TXCW_ASYM_PAUSE)
+ && (pcs_lpab & TXCW_SYM_PAUSE)
+ && (pcs_lpab & TXCW_ASYM_PAUSE))
+ mii->mii_media_active |= IFM_FLOW
+ | IFM_ETH_TXPAUSE;
+ else if ((pcs_adv & TXCW_SYM_PAUSE)
+ && (pcs_adv & TXCW_ASYM_PAUSE)
+ && ((pcs_lpab & TXCW_SYM_PAUSE) == 0)
+ && (pcs_lpab & TXCW_ASYM_PAUSE))
+ mii->mii_media_active |= IFM_FLOW
+ | IFM_ETH_RXPAUSE;
+ }
+ /* Update LED */
+ wm_tbi_serdes_set_linkled(sc);
+ } else {
+ DPRINTF(WM_DEBUG_LINK,
+ ("%s: LINK: Receive sequence error\n",
+ device_xname(sc->sc_dev)));
+ }
+}
+
+/*
* wm_linkintr:
*
* Helper; handle link interrupts.
@@ -6034,6 +6138,9 @@
if (sc->sc_flags & WM_F_HAS_MII)
wm_linkintr_gmii(sc, icr);
+ else if ((sc->sc_mediatype == WM_MEDIATYPE_SERDES)
+ && (sc->sc_type >= WM_T_82575))
+ wm_linkintr_serdes(sc, icr);
else
wm_linkintr_tbi(sc, icr);
}
Home |
Main Index |
Thread Index |
Old Index