summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrad <brad@openbsd.org>2014-11-19 02:37:41 +0000
committerbrad <brad@openbsd.org>2014-11-19 02:37:41 +0000
commit3d05a524502df298c3fe30e0754399225701f3bd (patch)
tree2d4550a899d91922be92a9dfe5b6fe429d311dbd
parentSupport the ".if v" conditional operator (vroff mode, always false) (diff)
downloadwireguard-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.c43
-rw-r--r--sys/dev/ic/rtl81x9reg.h3
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 */