Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci - Make new wm_phy_post_reset() and use this func...
details: https://anonhg.NetBSD.org/src/rev/4f2639032340
branches: trunk
changeset: 354705:4f2639032340
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Mon Jun 26 04:22:46 2017 +0000
description:
- 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.
diffstat:
sys/dev/pci/if_wm.c | 202 ++++++++++++++++++++++++++++++++----------------
sys/dev/pci/if_wmreg.h | 11 ++-
2 files changed, 145 insertions(+), 68 deletions(-)
diffs (truncated from 366 to 300 lines):
diff -r aa59592b22e4 -r 4f2639032340 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Mon Jun 26 04:18:14 2017 +0000
+++ b/sys/dev/pci/if_wm.c Mon Jun 26 04:22:46 2017 +0000
@@ -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_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 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 @@
}
}
+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 @@
sc->phy.release(sc);
wm_get_cfg_done(sc);
+ wm_phy_post_reset(sc);
}
static void
@@ -4371,6 +4415,9 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
| __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) {
+ uint16_t max_snoop, max_nosnoop, max_ltr_enc;
+ uint32_t status;
+ uint16_t speed;
pcireg_t preg;
- uint16_t max_snoop, max_nosnoop, max_ltr_enc;
-
+
+ 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 @@
* 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 @@
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 */
Home |
Main Index |
Thread Index |
Old Index