summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_ste.c
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2004-03-31 21:10:01 +0000
committerru <ru@FreeBSD.org>2004-03-31 21:10:01 +0000
commitdb8b2a901c7b7ab54804456a67f245f78d3a525d (patch)
tree042883642d009467fe70b15cc01a4697f927b11b /sys/pci/if_ste.c
parentec79f6e2f06427778bc8e6e17228adda2ae7ea3f (diff)
downloadFreeBSD-src-db8b2a901c7b7ab54804456a67f245f78d3a525d.zip
FreeBSD-src-db8b2a901c7b7ab54804456a67f245f78d3a525d.tar.gz
Under a heavy RX load, at least with D-Link DFE-550TX adapters,
the driver's RX ring head may fall behind the chip, causing the stuck traffic, disordered packets, etc. Work around this by adopting the technique of resyncing RX head used in dc(4) and xl(4) drivers, but do it in a slightly different place to reduce the number of resyncs needed. Also, set the NIC's RX polling period to a more meaningful value, to stop overloading the PCI bus (this also reduces the number of resyncs by a factor of 3 or more in a long run; the actual number is very dependent on a nature of the traffic). Maintain the statistics counter as the hw.ste_rxsyncs sysctl. In cooperation with: Vsevolod Lobko OK'ed by: ambrisko MFC after: 5 days
Diffstat (limited to 'sys/pci/if_ste.c')
-rw-r--r--sys/pci/if_ste.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/pci/if_ste.c b/sys/pci/if_ste.c
index 9fe4613..8e53dd3 100644
--- a/sys/pci/if_ste.c
+++ b/sys/pci/if_ste.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -162,6 +163,9 @@ static devclass_t ste_devclass;
DRIVER_MODULE(ste, pci, ste_driver, ste_devclass, 0, 0);
DRIVER_MODULE(miibus, ste, miibus_driver, miibus_devclass, 0, 0);
+static int ste_rxsyncs;
+SYSCTL_INT(_hw, OID_AUTO, ste_rxsyncs, CTLFLAG_RW, &ste_rxsyncs, 0, "");
+
#define STE_SETBIT4(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
@@ -758,6 +762,19 @@ ste_rxeof(sc)
ifp = &sc->arpcom.ac_if;
+ if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status == 0) {
+ cur_rx = sc->ste_cdata.ste_rx_head;
+ do {
+ cur_rx = cur_rx->ste_next;
+ /* If the ring is empty, just return. */
+ if (cur_rx == sc->ste_cdata.ste_rx_head)
+ return;
+ } while (cur_rx->ste_ptr->ste_status == 0);
+ /* We've fallen behind the chip: catch it. */
+ sc->ste_cdata.ste_rx_head = cur_rx;
+ ++ste_rxsyncs;
+ };
+
while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)
& STE_RXSTAT_DMADONE) {
#ifdef DEVICE_POLLING
@@ -1309,7 +1326,7 @@ ste_init(xsc)
}
/* Set RX polling interval */
- CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 1);
+ CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 64);
/* Init TX descriptors */
ste_init_tx_list(sc);
OpenPOWER on IntegriCloud