Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Mar 2004 18:00:02 +0300
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        Doug Ambrisko <ambrisko@FreeBSD.org>
Cc:        net@FreeBSD.org
Subject:   ste(4) NIC's RX ring head may get ahead of the driver [PATCH]
Message-ID:  <20040330150001.GB94442@ip.net.ua>

next in thread | raw e-mail | index | archive | help

--qtZFehHsKgwS5rPz
Content-Type: multipart/mixed; boundary="St7VIuEGZ6dlpu13"
Content-Disposition: inline


--St7VIuEGZ6dlpu13
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hey Doug,

I'm writing to you because you were the last who touched this driver
seriously, but since it's been 1,5 years ago, I'm also Cc:ing the
freebsd-net mailing list, as I'm not sure if you're still interested
in this driver.

To make the long story short, under a heavy RX load, the ste(4) NIC's
RX ring head may get ahead of what driver thinks, bringing all sort
of havoc like stuck traffic, disordered packets, etc.  The NIC never
gets out of this state, and the only workaround is to reset the chip,
and so we did for some time (by adding the IFF_LINK2 handler to call
the driver's watchdog function).

A similar problem is known to exist with other NICs, such as dc(4)
and xl(4), and their drivers have workarounds for this situation.

We've adopted the approach used by dc(4) and xl(4), but instead of
seeing if we need to re-synchronize the head _after_ receiving (like
dc(4) and xl(4) drivers do), we do it at the beginning of ste_rxeof().
As statistics shows, the number of resyncs needed is smaller by a
factor of 3 or more in this case, because often the RxDMAComplete
interrupt is generated when RX ring is completely empty(!), and as
NIC continues to do DMA and fill the RX ring while we're still
servicing the RxDMAComplete interrupt, we did more resyncs than was
actually necessary.

Also, we were able to further reduce the number of resyncs by setting
the RxDMAPollPeriod to a higher value.  320ns looked like an overkill
here, and I'm not sure why you have chosen it in the first place,
when adding polling support for RX in the driver.  Also, we believe
that this setting may be responsible for what you referred to as:

> This card still has seemingly unfixable issues under heavy RX load in
> which the card takes over the PCI bus.

in the commit log for revision 1.33 of if_ste.c.

Attached is the patch (for RELENG_4) we're currently using, and are
quite happy with.  If anyone is using ste(4) NICs and is experiencing
similar problems, I'd be glad to hear the reports about this patch.


Cheers,
--=20
Ruslan Ermilov
ru@FreeBSD.org
FreeBSD committer

--St7VIuEGZ6dlpu13
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=p
Content-Transfer-Encoding: quoted-printable

Index: if_ste.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/cvs/ipnet/freebsd/src/sys/pci/if_ste.c,v
retrieving revision 1.1.1.2
retrieving revision 1.7
diff -u -p -r1.1.1.2 -r1.7
--- if_ste.c	29 Mar 2004 11:47:42 -0000	1.1.1.2
+++ if_ste.c	29 Mar 2004 13:41:47 -0000	1.7
@@ -30,6 +30,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/pci/if_ste.c,v 1.14.2.10 2004/03/25 08:49:22 ru Exp $
+ * $IPNet: ipnet/freebsd/src/sys/pci/if_ste.c,v 1.7 2004/03/29 13:41:47 ru=
 Exp $
  */
=20
 #include <sys/param.h>
@@ -39,6 +40,7 @@
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
+#include <sys/sysctl.h>
=20
 #include <net/if.h>
 #include <net/if_arp.h>
@@ -163,6 +165,10 @@ static driver_t ste_driver =3D {
=20
 static devclass_t ste_devclass;
=20
+static int ste_rxresync;
+SYSCTL_INT(_hw, OID_AUTO, ste_rxresync, CTLFLAG_RW,
+	&ste_rxresync, 0, "");
+
 DRIVER_MODULE(if_ste, pci, ste_driver, ste_devclass, 0, 0);
 DRIVER_MODULE(miibus, ste, miibus_driver, miibus_devclass, 0, 0);
=20
@@ -691,6 +697,19 @@ static void ste_rxeof(sc)
=20
 	ifp =3D &sc->arpcom.ac_if;
=20
+	if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status =3D=3D 0) {
+		cur_rx =3D sc->ste_cdata.ste_rx_head;
+		do {
+			cur_rx =3D cur_rx->ste_next;
+			/* If the ring is empty, just return. */
+			if (cur_rx =3D=3D sc->ste_cdata.ste_rx_head)
+				return;
+		} while (cur_rx->ste_ptr->ste_status =3D=3D 0);
+		/* We've fallen behind the chip: catch it. */
+		sc->ste_cdata.ste_rx_head =3D cur_rx;
+		++ste_rxresync;
+	};
+
 	while((rxstat =3D sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)
 	      & STE_RXSTAT_DMADONE) {
 		if ((STE_RX_LIST_CNT - count) < 3) {
@@ -1255,7 +1274,7 @@ static void ste_init(xsc)
 	}
=20
 	/* Set RX polling interval */
-	CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 1);
+	CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 64);
=20
 	/* Init TX descriptors */
 	ste_init_tx_list(sc);

--St7VIuEGZ6dlpu13--

--qtZFehHsKgwS5rPz
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQFAaYtxUkv4P6juNwoRAsDmAKCFR+dRSyOaZdnQ6MiIdPSCqX8iTQCggTVX
0JOAvF0tSgTiR7yRGmZUHgc=
=6VzZ
-----END PGP SIGNATURE-----

--qtZFehHsKgwS5rPz--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040330150001.GB94442>