summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-08-06 05:18:23 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-08-06 05:18:23 +0000
commit49e787eda17940329b83f3d5c12d4bff86f89b82 (patch)
treec147066df8c21624ec7eb95ed4f440a30630b3aa /sys/dev/ic
parent907e9019018d47c2d12a5b93597e602667138677 (diff)
With the PCIe devices, it looks as if issuing a TX command while
there is already a transmission in progress has no effect. In other words, if you send two packets in rapid succession, the second one may end up sitting in the TX DMA ring until another transmit command is issued later in the future. Basically, if re_txeof() sees that there are still descriptors outstanding, it needs to manually resume the TX DMA channel by issuing another TX command to make sure all transmissions are flushed out. (The PCI devices seem to keep the TX channel moving until all descriptors have been consumed. I'm not sure why the PCIe devices behave differently.) From wpaul@FreeBSD
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/re.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c
index 5faa23d6f79..aa099255aa7 100644
--- a/sys/dev/ic/re.c
+++ b/sys/dev/ic/re.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: re.c,v 1.39 2006/08/05 21:38:20 brad Exp $ */
+/* $OpenBSD: re.c,v 1.40 2006/08/06 05:18:22 brad Exp $ */
/* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */
/*
* Copyright (c) 1997, 1998-2003
@@ -1372,6 +1372,16 @@ re_txeof(struct rl_softc *sc)
}
/*
+ * Some chips will ignore a second TX request issued while an
+ * existing transmission is in progress. If the transmitter goes
+ * idle but there are still packets waiting to be sent, we need
+ * to restart the channel here to flush them out. This only seems
+ * to be required with the PCIe devices.
+ */
+ if (sc->rl_ldata.rl_tx_free < RL_TX_DESC_CNT(sc))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
+
+ /*
* If not all descriptors have been released reaped yet,
* reload the timer so that we will eventually get another
* interrupt that will cause us to re-enter this routine.