diff options
author | 2014-11-19 02:37:41 +0000 | |
---|---|---|
committer | 2014-11-19 02:37:41 +0000 | |
commit | 3d05a524502df298c3fe30e0754399225701f3bd (patch) | |
tree | 2d4550a899d91922be92a9dfe5b6fe429d311dbd | |
parent | Support the ".if v" conditional operator (vroff mode, always false) (diff) | |
download | wireguard-openbsd-3d05a524502df298c3fe30e0754399225701f3bd.tar.xz wireguard-openbsd-3d05a524502df298c3fe30e0754399225701f3bd.zip |
Add support for stopping the operation of the chipset within re_stop()
for newer generations of chipsets.
From FreeBSD
Tested with 8169, 8168C, 8168D, 8168G and by stsp@ with WOL.
-rw-r--r-- | sys/dev/ic/re.c | 43 | ||||
-rw-r--r-- | sys/dev/ic/rtl81x9reg.h | 3 |
2 files changed, 43 insertions, 3 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index 41b9e175616..0c4a1984460 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.159 2014/10/24 23:30:05 brad Exp $ */ +/* $OpenBSD: re.c,v 1.160 2014/11/19 02:37:41 brad Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -2070,7 +2070,44 @@ re_stop(struct ifnet *ifp) mii_down(&sc->sc_mii); - CSR_WRITE_1(sc, RL_COMMAND, 0x00); + /* + * Disable accepting frames to put RX MAC into idle state. + * Otherwise it's possible to get frames while stop command + * execution is in progress and controller can DMA the frame + * to already freed RX buffer during that period. + */ + CSR_WRITE_4(sc, RL_RXCFG, CSR_READ_4(sc, RL_RXCFG) & + ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_BROAD | RL_RXCFG_RX_INDIV | + RL_RXCFG_RX_MULTI)); + + if (sc->rl_flags & RL_FLAG_WAIT_TXPOLL) { + for (i = RL_TIMEOUT; i > 0; i--) { + if ((CSR_READ_1(sc, sc->rl_txstart) & + RL_TXSTART_START) == 0) + break; + DELAY(20); + } + if (i == 0) + printf("%s: stopping TX poll timed out!\n", + sc->sc_dev.dv_xname); + CSR_WRITE_1(sc, RL_COMMAND, 0x00); + } else if (sc->rl_flags & RL_FLAG_CMDSTOP) { + CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_STOPREQ | RL_CMD_TX_ENB | + RL_CMD_RX_ENB); + if (sc->rl_flags & RL_FLAG_CMDSTOP_WAIT_TXQ) { + for (i = RL_TIMEOUT; i > 0; i--) { + if ((CSR_READ_4(sc, RL_TXCFG) & + RL_TXCFG_QUEUE_EMPTY) != 0) + break; + DELAY(100); + } + if (i == 0) + printf("%s: stopping TXQ timed out!\n", + sc->sc_dev.dv_xname); + } + } else + CSR_WRITE_1(sc, RL_COMMAND, 0x00); + DELAY(1000); CSR_WRITE_2(sc, RL_IMR, 0x0000); CSR_WRITE_2(sc, RL_ISR, 0xFFFF); @@ -2262,6 +2299,8 @@ re_wol(struct ifnet *ifp, int enable) "(power-off) state\n", sc->sc_dev.dv_xname); } + re_iff(sc); + /* Temporarily enable write to configuration registers. */ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG); diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h index 531bf1accc7..3357553c517 100644 --- a/sys/dev/ic/rtl81x9reg.h +++ b/sys/dev/ic/rtl81x9reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9reg.h,v 1.86 2014/09/06 04:46:58 brad Exp $ */ +/* $OpenBSD: rtl81x9reg.h,v 1.87 2014/11/19 02:37:41 brad Exp $ */ /* * Copyright (c) 1997, 1998 @@ -149,6 +149,7 @@ */ #define RL_TXCFG_CLRABRT 0x00000001 /* retransmit aborted pkt */ #define RL_TXCFG_MAXDMA 0x00000700 /* max DMA burst size */ +#define RL_TXCFG_QUEUE_EMPTY 0x00000800 /* 8168E-VL or higher */ #define RL_TXCFG_CRCAPPEND 0x00010000 /* CRC append (0 = yes) */ #define RL_TXCFG_LOOPBKTST 0x00060000 /* loopback test */ #define RL_TXCFG_IFG2 0x00080000 /* 8169 only */ |