Module Name: src Committed By: msaitoh Date: Wed Nov 16 07:24:52 UTC 2016
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h Log Message: Add three workarounds for PCH_{LPT,SPT}. To generate a diff of this commit: cvs rdiff -u -r1.444 -r1.445 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.91 -r1.92 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.444 src/sys/dev/pci/if_wm.c:1.445 --- src/sys/dev/pci/if_wm.c:1.444 Mon Nov 14 05:38:39 2016 +++ src/sys/dev/pci/if_wm.c Wed Nov 16 07:24:52 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.444 2016/11/14 05:38:39 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.445 2016/11/16 07:24:52 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.444 2016/11/14 05:38:39 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.445 2016/11/16 07:24:52 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -862,6 +862,7 @@ static void wm_set_mdio_slow_mode_hv(str 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 *); +static int wm_platform_pm_pch_lpt(struct wm_softc *, bool); static void wm_pll_workaround_i210(struct wm_softc *); CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), @@ -7507,6 +7508,7 @@ wm_linkintr_gmii(struct wm_softc *sc, ui __func__)); if (icr & ICR_LSC) { + uint32_t reg; uint32_t status = CSR_READ(sc, WMREG_STATUS); if ((sc->sc_type == WM_T_ICH8) && ((status & STATUS_LU) == 0)) @@ -7575,6 +7577,44 @@ wm_linkintr_gmii(struct wm_softc *sc, ui HV_MUX_DATA_CTRL_GEN_TO_MAC); } } + /* + * I217 Packet Loss issue: + * ensure that FEXTNVM4 Beacon Duration is set correctly + * on power up. + * Set the Beacon Duration for I217 to 8 usec + */ + if ((sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) { + reg = CSR_READ(sc, WMREG_FEXTNVM4); + reg &= ~FEXTNVM4_BEACON_DURATION; + reg |= FEXTNVM4_BEACON_DURATION_8US; + CSR_WRITE(sc, WMREG_FEXTNVM4, reg); + } + + /* XXX Work-around I218 hang issue */ + /* e1000_k1_workaround_lpt_lp() */ + + if ((sc->sc_type == WM_T_PCH_LPT) + || (sc->sc_type == WM_T_PCH_SPT)) { + /* + * Set platform power management values for Latency + * Tolerance Reporting (LTR) + */ + wm_platform_pm_pch_lpt(sc, + ((sc->sc_mii.mii_media_status & IFM_ACTIVE) + != 0)); + } + + /* FEXTNVM6 K1-off workaround */ + if (sc->sc_type == WM_T_PCH_SPT) { + reg = CSR_READ(sc, WMREG_FEXTNVM6); + if (CSR_READ(sc, WMREG_PCIEANACFG) + & FEXTNVM6_K1_OFF_ENABLE) + reg |= FEXTNVM6_K1_OFF_ENABLE; + else + reg &= ~FEXTNVM6_K1_OFF_ENABLE; + CSR_WRITE(sc, WMREG_FEXTNVM6, reg); + } } else if (icr & ICR_RXSEQ) { DPRINTF(WM_DEBUG_LINK, ("%s: LINK Receive sequence error\n", device_xname(sc->sc_dev))); @@ -12525,6 +12565,90 @@ wm_reset_mdicnfg_82580(struct wm_softc * CSR_WRITE(sc, WMREG_MDICNFG, reg); } +static int +wm_platform_pm_pch_lpt(struct wm_softc *sc, bool link) +{ + uint32_t reg = __SHIFTIN(link, LTRV_NONSNOOP_REQ) + | __SHIFTIN(link, LTRV_SNOOP_REQ) | LTRV_SEND; + uint32_t rxa; + uint16_t scale = 0, lat_enc = 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; + + rxa = CSR_READ(sc, WMREG_PBA) & PBA_RXA_MASK; + + /* + * Determine the maximum latency tolerated by the device. + * + * Per the PCIe spec, the tolerated latencies are encoded as + * a 3-bit encoded scale (only 0-5 are valid) multiplied by + * a 10-bit value (0-1023) to provide a range from 1 ns to + * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, + * 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; + 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; + } + lat_ns /= speed; + } + value = lat_ns; + + while (value > LTRV_VALUE) { + scale ++; + value = howmany(value, __BIT(5)); + } + if (scale > LTRV_SCALE_MAX) { + printf("%s: Invalid LTR latency scale %d\n", + device_xname(sc->sc_dev), scale); + return -1; + } + lat_enc = (uint16_t)(__SHIFTIN(scale, LTRV_SCALE) | value); + + preg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, + WM_PCI_LTR_CAP_LPT); + max_snoop = preg & 0xffff; + max_nosnoop = preg >> 16; + + max_ltr_enc = MAX(max_snoop, max_nosnoop); + + if (lat_enc > max_ltr_enc) { + lat_enc = max_ltr_enc; + } + } + /* Snoop and No-Snoop latencies the same */ + reg |= lat_enc | __SHIFTIN(lat_enc, LTRV_NONSNOOP); + CSR_WRITE(sc, WMREG_LTRV, reg); + + return 0; +} + /* * I210 Errata 25 and I211 Errata 10 * Slow System Clock. Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.91 src/sys/dev/pci/if_wmreg.h:1.92 --- src/sys/dev/pci/if_wmreg.h:1.91 Mon Nov 14 08:48:03 2016 +++ src/sys/dev/pci/if_wmreg.h Wed Nov 16 07:24:52 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.91 2016/11/14 08:48:03 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.92 2016/11/16 07:24:52 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -202,6 +202,8 @@ struct livengood_tcpip_ctxdesc { /* registers for FLASH access on ICH8 */ #define WM_ICH8_FLASH 0x0014 +#define WM_PCI_LTR_CAP_LPT 0xa8 + /* XXX Only for PCH_SPT? */ #define WM_PCI_DESCRING_STATUS 0xe4 #define DESCRING_STATUS_FLUSH_REQ __BIT(8) @@ -255,10 +257,10 @@ struct livengood_tcpip_ctxdesc { #define STATUS_FUNCID_MASK 3 /* ... */ #define STATUS_TXOFF (1U << 4) /* Tx paused */ #define STATUS_TBIMODE (1U << 5) /* fiber mode (Livengood) */ -#define STATUS_SPEED(x) ((x) << 6) /* speed indication */ -#define STATUS_SPEED_10 STATUS_SPEED(0) -#define STATUS_SPEED_100 STATUS_SPEED(1) -#define STATUS_SPEED_1000 STATUS_SPEED(2) +#define STATUS_SPEED __BITS(7, 6) /* speed indication */ +#define STATUS_SPEED_10 0 +#define STATUS_SPEED_100 1 +#define STATUS_SPEED_1000 2 #define STATUS_ASDV(x) ((x) << 8) /* auto speed det. val. (Livengood) */ #define STATUS_LAN_INIT_DONE (1U << 9) /* Lan Init Completion by NVM */ #define STATUS_MTXCKOK (1U << 10) /* MTXD clock running */ @@ -308,6 +310,9 @@ struct livengood_tcpip_ctxdesc { #define EERD_ADDR_SHIFT 2 /* Shift to the address bits */ #define EERD_DATA_SHIFT 16 /* Offset to data in EEPROM read/write registers */ +#define WMREG_FEXTNVM6 0x0010 /* Future Extended NVM 6 */ +#define FEXTNVM6_K1_OFF_ENABLE __BIT(31) + #define WMREG_CTRL_EXT 0x0018 /* Extended Device Control Register */ #define CTRL_EXT_NSICR __BIT(0) /* Non Interrupt clear on read */ #define CTRL_EXT_GPI_EN(x) (1U << (x)) /* gpin interrupt enable */ @@ -368,6 +373,11 @@ struct livengood_tcpip_ctxdesc { #define SCTL_CTL_POLL_TIMEOUT 640 #define SCTL_DISABLE_SERDES_LOOPBACK 0x0400 +#define WMREG_FEXTNVM4 0x0024 /* Future Extended NVM 4 - RW */ +#define FEXTNVM4_BEACON_DURATION __BITS(2, 0) +#define FEXTNVM4_BEACON_DURATION_8US 0x7 +#define FEXTNVM4_BEACON_DURATION_16US 0x3 + #define WMREG_FCAL 0x0028 /* Flow Control Address Low */ #define FCAL_CONST 0x00c28001 /* Flow Control MAC addr low */ @@ -493,6 +503,15 @@ struct livengood_tcpip_ctxdesc { #define IVAR_MISC_TCPTIMER __BITS(0, 7) #define IVAR_MISC_OTHER __BITS(8, 15) +#define WMREG_LTRV 0x00f8 /* Latency Tolerance Reporting */ +#define LTRV_VALUE __BITS(9, 0) +#define LTRV_SCALE __BITS(12, 10) +#define LTRV_SCALE_MAX 5 +#define LTRV_SNOOP_REQ __BIT(15) +#define LTRV_SEND __BIT(30) +#define LTRV_NONSNOOP __BITS(31, 16) +#define LTRV_NONSNOOP_REQ __BIT(31) + #define WMREG_RCTL 0x0100 /* Receive Control */ #define RCTL_EN (1U << 1) /* receiver enable */ #define RCTL_SBP (1U << 2) /* store bad packets */ @@ -728,6 +747,8 @@ struct livengood_tcpip_ctxdesc { #define PHY_CTRL_NOND0A_GBE_DIS (1 << 3) #define PHY_CTRL_GBE_DIS (1 << 6) +#define WMREG_PCIEANACFG 0x0f18 /* PCIE Analog Config */ + #define WMREG_IOSFPC 0x0f28 /* Tx corrupted data */ #define WMREG_PBA 0x1000 /* Packet Buffer Allocation */ @@ -749,6 +770,7 @@ struct livengood_tcpip_ctxdesc { #define PBA_40K 0x0028 #define PBA_48K 0x0030 /* 48K, default Rx allocation */ #define PBA_64K 0x0040 +#define PBA_RXA_MASK __BITS(15, 0) #define WMREG_PBS 0x1008 /* Packet Buffer Size (ICH) */