Module Name: src
Committed By: msaitoh
Date: Mon Jun 26 04:22:47 UTC 2017
Modified Files:
src/sys/dev/pci: if_wm.c if_wmreg.h
Log Message:
- Make new wm_phy_post_reset() and use this function at all location after
reseting phy.
- Move the location of calling wm_get_hw_control. Same as Linux.
- Add I219 specific wokaround for legacy interrupt. From OpenBSD.
- Move the location of calling wm_lplu_d0_disable().
- Fix latency calculation in wm_platform_pm_pch_lpt().
- Set OBFF water mark and enable OBFF on PCH_LPT and newer.
To generate a diff of this commit:
cvs rdiff -u -r1.516 -r1.517 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.99 -r1.100 src/sys/dev/pci/if_wmreg.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.516 src/sys/dev/pci/if_wm.c:1.517
--- src/sys/dev/pci/if_wm.c:1.516 Mon Jun 26 04:18:14 2017
+++ src/sys/dev/pci/if_wm.c Mon Jun 26 04:22:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.516 2017/06/26 04:18:14 msaitoh Exp $ */
+/* $NetBSD: if_wm.c,v 1.517 2017/06/26 04:22:46 msaitoh 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.516 2017/06/26 04:18:14 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.517 2017/06/26 04:22:46 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -679,6 +679,7 @@ static void wm_set_pcie_completion_timeo
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_phy_post_reset(struct wm_softc *);
static void wm_initialize_hardware_bits(struct wm_softc *);
static uint32_t wm_rxpbs_adjust_82580(uint32_t);
static void wm_reset_phy(struct wm_softc *);
@@ -930,6 +931,7 @@ static bool wm_phy_is_accessible_pchlan(
static void wm_toggle_lanphypc_pch_lpt(struct wm_softc *);
static int wm_platform_pm_pch_lpt(struct wm_softc *, bool);
static void wm_pll_workaround_i210(struct wm_softc *);
+static void wm_legacy_irq_quirk_spt(struct wm_softc *);
CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -3659,6 +3661,47 @@ wm_get_cfg_done(struct wm_softc *sc)
}
}
+void
+wm_phy_post_reset(struct wm_softc *sc)
+{
+ uint32_t reg;
+
+ /* This function is only for ICH8 and newer. */
+ if (sc->sc_type < WM_T_ICH8)
+ return;
+
+ if (wm_phy_resetisblocked(sc)) {
+ /* XXX */
+ device_printf(sc->sc_dev, " PHY is blocked\n");
+ return;
+ }
+
+ /* Allow time for h/w to get to quiescent state after reset */
+ delay(10*1000);
+
+ /* Perform any necessary post-reset workarounds */
+ if (sc->sc_type == WM_T_PCH)
+ wm_hv_phy_workaround_ich8lan(sc);
+ if (sc->sc_type == WM_T_PCH2)
+ wm_lv_phy_workaround_ich8lan(sc);
+
+ /* Clear the host wakeup bit after lcd reset */
+ if (sc->sc_type >= WM_T_PCH) {
+ reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
+ BM_PORT_GEN_CFG);
+ reg &= ~BM_WUC_HOST_WU_BIT;
+ wm_gmii_hv_writereg(sc->sc_dev, 2,
+ BM_PORT_GEN_CFG, reg);
+ }
+
+ /*
+ * XXX Configure the LCD with th extended configuration region
+ * in NVM
+ */
+
+ /* Configure the LCD with the OEM bits in NVM */
+}
+
/* Init hardware bits */
void
wm_initialize_hardware_bits(struct wm_softc *sc)
@@ -3938,6 +3981,7 @@ wm_reset_phy(struct wm_softc *sc)
sc->phy.release(sc);
wm_get_cfg_done(sc);
+ wm_phy_post_reset(sc);
}
static void
@@ -4371,6 +4415,9 @@ wm_reset(struct wm_softc *sc)
break;
}
+ if (phy_reset != 0)
+ wm_phy_post_reset(sc);
+
if ((sc->sc_type == WM_T_82580)
|| (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)) {
/* clear global device reset status bit */
@@ -4403,15 +4450,6 @@ wm_reset(struct wm_softc *sc)
if ((sc->sc_type >= WM_T_I350) && (sc->sc_type <= WM_T_I211))
wm_set_eee_i350(sc);
- /* Clear the host wakeup bit after lcd reset */
- if (sc->sc_type >= WM_T_PCH) {
- reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
- BM_PORT_GEN_CFG);
- reg &= ~BM_WUC_HOST_WU_BIT;
- wm_gmii_hv_writereg(sc->sc_dev, 2,
- BM_PORT_GEN_CFG, reg);
- }
-
/*
* For PCH, this write will make sure that any noise will be detected
* as a CRC error and be dropped rather than show up as a bad packet
@@ -5091,6 +5129,10 @@ wm_init_locked(struct ifnet *ifp)
ifp->if_collisions += CSR_READ(sc, WMREG_COLC);
ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC);
+ /* AMT based hardware can now take control from firmware */
+ if ((sc->sc_flags & WM_F_HAS_AMT) != 0)
+ wm_get_hw_control(sc);
+
/* PCH_SPT hardware workaround */
if (sc->sc_type == WM_T_PCH_SPT)
wm_flush_desc_rings(sc);
@@ -5098,9 +5140,9 @@ wm_init_locked(struct ifnet *ifp)
/* Reset the chip to a known state. */
wm_reset(sc);
- /* AMT based hardware can now take control from firmware */
- if ((sc->sc_flags & WM_F_HAS_AMT) != 0)
- wm_get_hw_control(sc);
+ if ((sc->sc_type == WM_T_PCH_SPT) &&
+ pci_intr_type(sc->sc_pc, sc->sc_intrs[0]) == PCI_INTR_TYPE_INTX)
+ wm_legacy_irq_quirk_spt(sc);
/* Init hardware bits */
wm_initialize_hardware_bits(sc);
@@ -8528,7 +8570,7 @@ wm_intr_legacy(void *arg)
break;
if (handled == 0) {
DPRINTF(WM_DEBUG_TX,
- ("%s: INTx: got intr\n", device_xname(sc->sc_dev)));
+ ("%s: INTx: got intr\n",device_xname(sc->sc_dev)));
}
if (rndval == 0)
rndval = icr;
@@ -8934,34 +8976,7 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_PCH2:
case WM_T_PCH_LPT:
case WM_T_PCH_SPT:
- /* Allow time for h/w to get to a quiescent state afer reset */
- delay(10*1000);
-
- if (sc->sc_type == WM_T_PCH)
- wm_hv_phy_workaround_ich8lan(sc);
-
- if (sc->sc_type == WM_T_PCH2)
- wm_lv_phy_workaround_ich8lan(sc);
-
- /* Clear the host wakeup bit after lcd reset */
- if (sc->sc_type >= WM_T_PCH) {
- reg = wm_gmii_hv_readreg(sc->sc_dev, 2,
- BM_PORT_GEN_CFG);
- reg &= ~BM_WUC_HOST_WU_BIT;
- wm_gmii_hv_writereg(sc->sc_dev, 2,
- BM_PORT_GEN_CFG, reg);
- }
-
- /*
- * XXX Configure the LCD with th extended configuration region
- * in NVM
- */
-
- /* Disable D0 LPLU. */
- if (sc->sc_type >= WM_T_PCH) /* PCH* */
- wm_lplu_d0_disable_pch(sc);
- else
- wm_lplu_d0_disable(sc); /* ICH* */
+ wm_phy_post_reset(sc);
break;
default:
panic("%s: unknown type\n", __func__);
@@ -9422,6 +9437,12 @@ wm_gmii_mediachange(struct ifnet *ifp)
if ((ifp->if_flags & IFF_UP) == 0)
return 0;
+ /* Disable D0 LPLU. */
+ if (sc->sc_type >= WM_T_PCH) /* PCH* */
+ wm_lplu_d0_disable_pch(sc);
+ else
+ wm_lplu_d0_disable(sc); /* ICH* */
+
sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD);
sc->sc_ctrl |= CTRL_SLU;
if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)
@@ -13764,15 +13785,36 @@ wm_platform_pm_pch_lpt(struct wm_softc *
| __SHIFTIN(link, LTRV_SNOOP_REQ) | LTRV_SEND;
uint32_t rxa;
uint16_t scale = 0, lat_enc = 0;
+ int32_t obff_hwm = 0;
int64_t lat_ns, value;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
if (link) {
- pcireg_t preg;
uint16_t max_snoop, max_nosnoop, max_ltr_enc;
+ uint32_t status;
+ uint16_t speed;
+ pcireg_t preg;
+
+ status = CSR_READ(sc, WMREG_STATUS);
+ switch (__SHIFTOUT(status, STATUS_SPEED)) {
+ case STATUS_SPEED_10:
+ speed = 10;
+ break;
+ case STATUS_SPEED_100:
+ speed = 100;
+ break;
+ case STATUS_SPEED_1000:
+ speed = 1000;
+ break;
+ default:
+ device_printf(sc->sc_dev, "Unknown speed "
+ "(status = %08x)\n", status);
+ return -1;
+ }
+ /* Rx Packet Buffer Allocation size (KB) */
rxa = CSR_READ(sc, WMREG_PBA) & PBA_RXA_MASK;
/*
@@ -13785,31 +13827,12 @@ wm_platform_pm_pch_lpt(struct wm_softc *
* 1=2^5ns, 2=2^10ns,...5=2^25ns.
*/
lat_ns = ((int64_t)rxa * 1024 -
- (2 * (int64_t)sc->sc_ethercom.ec_if.if_mtu)) * 8 * 1000;
+ (2 * ((int64_t)sc->sc_ethercom.ec_if.if_mtu
+ + ETHER_HDR_LEN))) * 8 * 1000;
if (lat_ns < 0)
lat_ns = 0;
- else {
- uint32_t status;
- uint16_t speed;
-
- status = CSR_READ(sc, WMREG_STATUS);
- switch (__SHIFTOUT(status, STATUS_SPEED)) {
- case STATUS_SPEED_10:
- speed = 10;
- break;
- case STATUS_SPEED_100:
- speed = 100;
- break;
- case STATUS_SPEED_1000:
- speed = 1000;
- break;
- default:
- printf("%s: Unknown speed (status = %08x)\n",
- device_xname(sc->sc_dev), status);
- return -1;
- }
+ else
lat_ns /= speed;
- }
value = lat_ns;
while (value > LTRV_VALUE) {
@@ -13833,12 +13856,39 @@ wm_platform_pm_pch_lpt(struct wm_softc *
if (lat_enc > max_ltr_enc) {
lat_enc = max_ltr_enc;
+ lat_ns = __SHIFTOUT(lat_enc, PCI_LTR_MAXSNOOPLAT_VAL)
+ * PCI_LTR_SCALETONS(
+ __SHIFTOUT(lat_enc,
+ PCI_LTR_MAXSNOOPLAT_SCALE));
+ }
+
+ if (lat_ns) {
+ lat_ns *= speed * 1000;
+ lat_ns /= 8;
+ lat_ns /= 1000000000;
+ obff_hwm = (int32_t)(rxa - lat_ns);
+ }
+ if ((obff_hwm < 0) || (obff_hwm > SVT_OFF_HWM)) {
+ device_printf(sc->sc_dev, "Invalid high water mark %d"
+ "(rxa = %d, lat_ns = %d)\n",
+ obff_hwm, (int32_t)rxa, (int32_t)lat_ns);
+ return -1;
}
}
/* Snoop and No-Snoop latencies the same */
reg |= lat_enc | __SHIFTIN(lat_enc, LTRV_NONSNOOP);
CSR_WRITE(sc, WMREG_LTRV, reg);
+ /* Set OBFF high water mark */
+ reg = CSR_READ(sc, WMREG_SVT) & ~SVT_OFF_HWM;
+ reg |= obff_hwm;
+ CSR_WRITE(sc, WMREG_SVT, reg);
+
+ /* Enable OBFF */
+ reg = CSR_READ(sc, WMREG_SVCR);
+ reg |= SVCR_OFF_EN | SVCR_OFF_MASKINT;
+ CSR_WRITE(sc, WMREG_SVCR, reg);
+
return 0;
}
@@ -13916,3 +13966,21 @@ wm_pll_workaround_i210(struct wm_softc *
if (wa_done)
aprint_verbose_dev(sc->sc_dev, "I210 workaround done\n");
}
+
+static void
+wm_legacy_irq_quirk_spt(struct wm_softc *sc)
+{
+ uint32_t reg;
+
+ DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
+ device_xname(sc->sc_dev), __func__));
+ KASSERT(sc->sc_type == WM_T_PCH_SPT);
+
+ reg = CSR_READ(sc, WMREG_FEXTNVM7);
+ reg |= FEXTNVM7_SIDE_CLK_UNGATE;
+ CSR_WRITE(sc, WMREG_FEXTNVM7, reg);
+
+ reg = CSR_READ(sc, WMREG_FEXTNVM9);
+ reg |= FEXTNVM9_IOSFSB_CLKGATE_DIS | FEXTNVM9_IOSFSB_CLKREQ_DIS;
+ CSR_WRITE(sc, WMREG_FEXTNVM9, reg);
+}
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.99 src/sys/dev/pci/if_wmreg.h:1.100
--- src/sys/dev/pci/if_wmreg.h:1.99 Mon Jun 26 04:09:02 2017
+++ src/sys/dev/pci/if_wmreg.h Mon Jun 26 04:22:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.99 2017/06/26 04:09:02 msaitoh Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.100 2017/06/26 04:22:46 msaitoh Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -728,6 +728,13 @@ struct livengood_tcpip_ctxdesc {
#define IVAR_MISC_TCPTIMER __BITS(0, 7)
#define IVAR_MISC_OTHER __BITS(8, 15)
+#define WMREG_SVCR 0x00f0
+#define SVCR_OFF_EN __BIT(0)
+#define SVCR_OFF_MASKINT __BIT(12)
+
+#define WMREG_SVT 0x00f4
+#define SVT_OFF_HWM __BITS(4, 0)
+
#define WMREG_LTRV 0x00f8 /* Latency Tolerance Reporting */
#define LTRV_VALUE __BITS(9, 0)
#define LTRV_SCALE __BITS(12, 10)
@@ -1302,6 +1309,8 @@ struct livengood_tcpip_ctxdesc {
#define WMREG_GCR2 0x5b64 /* 3GPIO Control Register 2 */
#define WMREG_FEXTNVM9 0x5bb4 /* Future Extended NVM 9 */
+#define FEXTNVM9_IOSFSB_CLKGATE_DIS __BIT(11)
+#define FEXTNVM9_IOSFSB_CLKREQ_DIS __BIT(12)
#define WMREG_FEXTNVM11 0x5bbc /* Future Extended NVM 11 */
#define FEXTNVM11_DIS_MULRFIX __BIT(13) /* Disable MULR fix */