summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2011-11-23 22:07:13 +0000
committeryongari <yongari@FreeBSD.org>2011-11-23 22:07:13 +0000
commit59c40435df4cc5e4b692d0b1588298e0754c3342 (patch)
treede23de00ff8be770055f95feb245304452fd46bd
parent7deb56f7c27202bf2235ca83399ccec82047253a (diff)
downloadFreeBSD-src-59c40435df4cc5e4b692d0b1588298e0754c3342.zip
FreeBSD-src-59c40435df4cc5e4b692d0b1588298e0754c3342.tar.gz
Make sure to stop TX MAC before freeing queued TX frames.
For RTL8111DP, check if the TX MAC is active by reading RL_GTXSTART register. For RTL8402/8168E-VL/8168F/8411, wait until TX queue is empty.
-rw-r--r--sys/dev/re/if_re.c42
-rw-r--r--sys/pci/if_rlreg.h35
2 files changed, 56 insertions, 21 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 462518c..ad10400 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -1401,13 +1401,18 @@ re_attach(device_t dev)
RL_FLAG_AUTOPAD | RL_FLAG_MACSLEEP;
break;
case RL_HWREV_8401E:
- case RL_HWREV_8402:
case RL_HWREV_8105E:
case RL_HWREV_8105E_SPIN1:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD;
break;
+ case RL_HWREV_8402:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
+ RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
+ RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD |
+ RL_FLAG_CMDSTOP_WAIT_TXQ;
+ break;
case RL_HWREV_8168B_SPIN1:
case RL_HWREV_8168B_SPIN2:
sc->rl_flags |= RL_FLAG_WOLRXENB;
@@ -1424,11 +1429,15 @@ re_attach(device_t dev)
/* FALLTHROUGH */
case RL_HWREV_8168CP:
case RL_HWREV_8168D:
- case RL_HWREV_8168DP:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2;
break;
+ case RL_HWREV_8168DP:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
+ RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_AUTOPAD |
+ RL_FLAG_JUMBOV2 | RL_FLAG_WAIT_TXPOLL;
+ break;
case RL_HWREV_8168E:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
@@ -1439,7 +1448,8 @@ re_attach(device_t dev)
case RL_HWREV_8411:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
- RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2;
+ RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
+ RL_FLAG_CMDSTOP_WAIT_TXQ;
break;
case RL_HWREV_8169_8110SB:
case RL_HWREV_8169_8110SBL:
@@ -3466,10 +3476,32 @@ re_stop(struct rl_softc *sc)
~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_MULTI |
RL_RXCFG_RX_BROAD));
- if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0)
+ if ((sc->rl_flags & RL_FLAG_WAIT_TXPOLL) != 0) {
+ 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)
+ device_printf(sc->rl_dev,
+ "stopping TX poll timed out!\n");
+ CSR_WRITE_1(sc, RL_COMMAND, 0x00);
+ } else if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0) {
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_STOPREQ | RL_CMD_TX_ENB |
RL_CMD_RX_ENB);
- else
+ if ((sc->rl_flags & RL_FLAG_CMDSTOP_WAIT_TXQ) != 0) {
+ 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)
+ device_printf(sc->rl_dev,
+ "stopping TXQ timed out!\n");
+ }
+ } else
CSR_WRITE_1(sc, RL_COMMAND, 0x00);
DELAY(1000);
CSR_WRITE_2(sc, RL_IMR, 0x0000);
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index dfad20b..a891b60 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -143,6 +143,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 */
@@ -897,22 +898,24 @@ struct rl_softc {
int rl_int_rx_act;
int rl_int_rx_mod;
uint32_t rl_flags;
-#define RL_FLAG_MSI 0x0001
-#define RL_FLAG_AUTOPAD 0x0002
-#define RL_FLAG_PHYWAKE_PM 0x0004
-#define RL_FLAG_PHYWAKE 0x0008
-#define RL_FLAG_JUMBOV2 0x0010
-#define RL_FLAG_PAR 0x0020
-#define RL_FLAG_DESCV2 0x0040
-#define RL_FLAG_MACSTAT 0x0080
-#define RL_FLAG_FASTETHER 0x0100
-#define RL_FLAG_CMDSTOP 0x0200
-#define RL_FLAG_MACRESET 0x0400
-#define RL_FLAG_MSIX 0x0800
-#define RL_FLAG_WOLRXENB 0x1000
-#define RL_FLAG_MACSLEEP 0x2000
-#define RL_FLAG_PCIE 0x4000
-#define RL_FLAG_LINK 0x8000
+#define RL_FLAG_MSI 0x00000001
+#define RL_FLAG_AUTOPAD 0x00000002
+#define RL_FLAG_PHYWAKE_PM 0x00000004
+#define RL_FLAG_PHYWAKE 0x00000008
+#define RL_FLAG_JUMBOV2 0x00000010
+#define RL_FLAG_PAR 0x00000020
+#define RL_FLAG_DESCV2 0x00000040
+#define RL_FLAG_MACSTAT 0x00000080
+#define RL_FLAG_FASTETHER 0x00000100
+#define RL_FLAG_CMDSTOP 0x00000200
+#define RL_FLAG_MACRESET 0x00000400
+#define RL_FLAG_MSIX 0x00000800
+#define RL_FLAG_WOLRXENB 0x00001000
+#define RL_FLAG_MACSLEEP 0x00002000
+#define RL_FLAG_WAIT_TXPOLL 0x00004000
+#define RL_FLAG_CMDSTOP_WAIT_TXQ 0x00008000
+#define RL_FLAG_PCIE 0x40000000
+#define RL_FLAG_LINK 0x80000000
};
#define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx)
OpenPOWER on IntegriCloud